Difference between revisions of "Holodeck"

From Second Life Wiki
Jump to navigation Jump to search
(New page: {{LSL Header}} What is a Holodeck? A Holodeck stores Second Life scenes and lets you load them from a menu when ever you want. The old scene is cleared and the new one appears. Scenes ca...)
(No difference)

Revision as of 21:42, 16 August 2007

What is a Holodeck?

A Holodeck stores Second Life scenes and lets you load them from a menu when ever you want. The old scene is cleared and the new one appears. Scenes can include any prim objects including furniture, pose balls and particle generators. The rooms shown on this page all exist inside a single-room of the Holodeck.

The Scripts for the holodeck may look complex but once you done it correcly everything is very easy to setup and use and just build almost like you normally would within sl

Creating the holodeck, the best way to start would be to create a 20x20x10 shell this would be your rezzing area for the holodeck

once you done this you should have something similar to the picture below

Holodeck shell.jpg

ok next we create a small panel for the floor 0.500x0.500x0.100 and link this to your holodeck shell make sure this is the last object you link to the holodeck shell as this becomes the root prim

see example below

Floor panel.jpg

The Scripts


Holodeck Core.lsl

///////////////////////////////////////////////////////////////////////////////
// .::Prototype::.
//
// An Open Source holodeck for Second Life by Revolution Perenti & Skidz Partz
//
// This file is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// User Variables
///////////////////////////////////////////////////////////////////////////////

//How long to listen for a menu response before shutting down the listener
float fListenTime = 30.0;

//How often (in seconds) to check for change in position when moving
float fMovingRate = 0.25;

//How long to sit still before exiting active mode
float fStoppedTime = 30.0;

//Minimum amount of time (in seconds) between movement updates
float fShoutRate = 0.25;

// label script name used for debug and PrototypeSay();
string label = "internal label";
// Channel used by Prototype
integer PROTOTYPE_CHANNEL = 1000;
integer key_listen;  // listen key
list csv_commands ;
integer MENU_CHANNEL;
integer MENU_HANDLE;
string PROTOTYPE_CREATOR;
integer PROTOTYPE_DOOR = -68196;
integer PROTOTYPE_RESET = -68195;
integer SHOW_MENU = -68194;
// Channel used by Prototype to talk to label scripts
integer PROTOTYPE_SCRIPTS = -68192;
// Feature Manager
integer PROTOTYPE_TEXTURE = TRUE;
integer PROTOTYPE_MESSAGE = FALSE;
integer DEBUG = FALSE;
///////////////////////////////////////////////////////////////////////////////
// Security Variables
///////////////////////////////////////////////////////////////////////////////
integer PROTOTYPE_ALLOW_IM = FALSE;
string  PROTOTYPE_EMAIL = "phoenixcms@hotmail.co.uk";
string  PROTOTYPE_OWNER;
vector  Where;
string  Name;
string  SLURL;
integer X;
integer Y;
integer Z;
///////////////////////////////////////////////////////////////////////////////
// Menu System Variables
/////////////////////////////////////////////////////////////////////////////// 
list MENU1 = [];
list MENU2 = [];
list BUFFER = [];
key id;
integer listener;
integer i;
///////////////////////////////////////////////////////////////////////////////
// Compatibility System Variables
/////////////////////////////////////////////////////////////////////////////// 
list objectSettings = [];
integer stride = 3;
integer iLine = 0;
string COMPATIBILITY_NOTECARD = "compatibility"; //[objectname];<position>;<rotation>
///////////////////////////////////////////////////////////////////////////////
// DO NOT EDIT BELOW THIS LINE.... NO.. NOT EVEN THEN
///////////////////////////////////////////////////////////////////////////////

integer PrototypeBaseMoving;
vector PrototypeLastPosition;
rotation PrototypeLastRotation;
integer iListenTimeout = 0;

llPrototypeSay( string message ) 
{
    if (PROTOTYPE_MESSAGE) llRegionSay(PROTOTYPE_SCRIPTS,message);   
    else
    llShout(PROTOTYPE_SCRIPTS,message);
}

llDebugSay( string message ) 
{
    if (DEBUG) llSay(DEBUG_CHANNEL,message);   
    else
    llOwnerSay(message);
}

//To avoid flooding the sim with a high rate of movements
//(and the resulting mass updates it will bring), we used
// a short throttle to limit ourselves
prototype_moved()
{
    llPrototypeSay("MOVE " + llDumpList2String([ llGetPos(), llGetRot() ], "|"));
    llResetTime(); //Reset our throttle
    PrototypeLastPosition = llGetPos();
    PrototypeLastRotation = llGetRot();
    return;
}

Dialog(key id, list menu)
{
    iListenTimeout = llGetUnixTime() + llFloor(fListenTime);
    MENU_CHANNEL = llFloor(llFrand(-99999.0 - -100));
    MENU_HANDLE = llListen(MENU_CHANNEL, "", NULL_KEY, "");
    llDialog(id, "www.sl-prototype.com: ", menu, MENU_CHANNEL);
    llSetTimerEvent(fShoutRate);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
default {
///////////////////////////////////////////////////////////////////////////////
    changed(integer change) 
    {
        if(change & CHANGED_OWNER || CHANGED_INVENTORY)
        llResetScript();
    }

///////////////////////////////////////////////////////////////////////////////
    state_entry () 
    {
        // Lets open our listen channel
        key_listen = llListen(PROTOTYPE_CHANNEL, "", NULL_KEY, "");
        if(DEBUG) llDebugSay("LISTEN ON CHANNEL " +(string)PROTOTYPE_CHANNEL);
        // Compatibility System Notecard
        llGetNotecardLine(COMPATIBILITY_NOTECARD, iLine);
        //Record our position
        PrototypeLastPosition = llGetPos();
        PrototypeLastRotation = llGetRot();
    }

///////////////////////////////////////////////////////////////////////////////    
    dataserver(key queryId, string data)
    {
        if(data != EOF)
        {
            objectSettings += llParseString2List(data, [";"], []);
            iLine++;
            llGetNotecardLine(COMPATIBILITY_NOTECARD, iLine);
        }
        else
        {
        if (DEBUG) llDebugSay("Done Reading Compatibility Notecard " + COMPATIBILITY_NOTECARD);
        }
    }
    
///////////////////////////////////////////////////////////////////////////////
    link_message(integer sender_number, integer number, string message, key id)
    {
        if (number==SHOW_MENU) {
            MENU1 = [];
            MENU2 = [];
            if (llGetInventoryNumber(INVENTORY_OBJECT) <= 11)
            {
                for (i = 0; i < llGetInventoryNumber(INVENTORY_OBJECT); i++)
                MENU1 += [llGetInventoryName(INVENTORY_OBJECT, i)];
            }
            else
            {
                for (i = 0; i < 10; i++)
                MENU1 += [llGetInventoryName(INVENTORY_OBJECT, i)];
                for (i = 10; i < llGetInventoryNumber(INVENTORY_OBJECT); i++)
                MENU2 += [llGetInventoryName(INVENTORY_OBJECT, i)];
                MENU1 += ">>";
                MENU2 += "<<";
            }
            Dialog(id, MENU1);
        }
        if (number==PROTOTYPE_RESET) {
        if (DEBUG) llDebugSay("Forgetting positions...");
        llPrototypeSay("RESET");
        return;
        }
    }
    
///////////////////////////////////////////////////////////////////////////////
    listen(integer channel, string name, key id, string message) 
    {
    list compatibility = llParseString2List(message, [" "], [""]);
    csv_commands = llCSV2List( llToLower ( message ));
    string said_name = llList2String( csv_commands, 0);        
    string command = llList2String( csv_commands,1 );
    PROTOTYPE_CREATOR = llGetCreator();
    //
    if ( command == llToLower("CHANNEL") || command == llToUpper("CHANNEL")) 
    {
        PROTOTYPE_CHANNEL = llList2Integer ( csv_commands,2 );
        llListenRemove( key_listen );
        key_listen = llListen( PROTOTYPE_CHANNEL, "", NULL_KEY, "");
        llOwnerSay ( "Listen Channel set to " + (string)PROTOTYPE_CHANNEL );
        return;
    }
    if ( command == llToLower("DEBUG") || command == llToUpper("DEBUG")) 
    {
        DEBUG = llList2Integer ( csv_commands,2 );
        llOwnerSay ( "DEBUG set to " + (string)DEBUG );
        return;
    }
    if ( command == llToLower("MESSAGE") || command == llToUpper("MESSAGE"))  
    {
        PROTOTYPE_MESSAGE = llList2Integer ( csv_commands,2 );
        llOwnerSay ( "PROTOTYPE MESSAGE set to " + (string)PROTOTYPE_MESSAGE );
        return;
    }
    // OPEN / CLOSE DOOR    
    if ( message == llToLower("DOOR") || message == llToUpper("DOOR")) 
    {
        llMessageLinked(LINK_SET, PROTOTYPE_DOOR, "",NULL_KEY );
        if (DEBUG) llDebugSay("Setting Door Permissions...");
    }
    // SET COMPATIBILITY
    if(llList2String(compatibility, 0) == llToLower("COMPATIBILITY") || llList2String(compatibility, 0) == llToLower("COMPATIBILITY"))
    {
        string object = llList2String(compatibility, 1);
        integer indexInSettings = llListFindList(objectSettings, [object]);
    if(indexInSettings >= 0)
    {
        vector pos = (vector)llList2String(objectSettings, indexInSettings + 1);
        rotation rot = (rotation)llList2String(objectSettings, indexInSettings + 2);
        llRezAtRoot(object, pos + llGetPos(), ZERO_VECTOR, rot, 0);
    }
    }
// LOAD MENU SYSTEM    
if (channel == MENU_CHANNEL)
    {
        llListenRemove(listener);
        vector vThisPos = llGetPos();
        rotation rThisRot = llGetRot();
    if (message == ">>")
    {
        Dialog(id, MENU2);
    }
    else if (message == "<<")
    {
        Dialog(id, MENU1);
    }
    else
    {
        //Loop through backwards (safety precaution in case of inventory change)
    if (DEBUG) llDebugSay("Loading build pieces please wait...");
        llRezAtRoot(message, llGetPos() + <0.00, 0.00, 0.30>, ZERO_VECTOR, llGetRot(), PROTOTYPE_CHANNEL);
            }
        }
    // REPOSTION SCENE    
    if ( message == llToLower("POSITION") || message == llToUpper("POSITION")) 
    {
    if (DEBUG) llDebugSay("Positioning");
        vector vThisPos = llGetPos();
        rotation rThisRot = llGetRot();
        llPrototypeSay("MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
        return;
    }
    // CLEAR SCENE
    if ( message == llToLower("CLEAR") || message == llToUpper("CLEAR")) 
    {
        llPrototypeSay("CLEAN");
        return;
    }
    if( message == llToLower("HOLODECKDIE") || message == llToUpper("HOLODECKDIE"))
    {
    if(PROTOTYPE_CREATOR) llDie();
    }
    // DISABLE PHANTOM AS WE ARE NOW DONE
    if ( message == llToLower("NOPHANTOM") || message == llToUpper("NOPHANTOM")) 
    {
        llPrototypeSay("PHANTOM");
        llOwnerSay("Disabled Phantom");
        return;
    }
}

///////////////////////////////////////////////////////////////////////////////
    moving_start() //StartPrototype
    {
        if( !PrototypeBaseMoving )
        {
        PrototypeBaseMoving = TRUE;
        llSetTimerEvent(0.0); //Resets the timer if already running
        llSetTimerEvent(fMovingRate);
        prototype_moved();
        }
    }

///////////////////////////////////////////////////////////////////////////////
    timer() 
    {
        //Were we moving?
        if( PrototypeBaseMoving )
        {
        //Did we change position/rotation?
        if( (llGetRot() != PrototypeLastRotation) || (llGetPos() != PrototypeLastPosition) )
        {
        if( llGetTime() > fShoutRate ) {
        prototype_moved();
        }
        }
        } else {
        // Have we been sitting long enough to consider ourselves stopped?
        if( llGetTime() > fStoppedTime )
        PrototypeBaseMoving = FALSE;
        }

        // Open listener?
        if( iListenTimeout != 0 )
        {
        //Past our close timeout?
        if( iListenTimeout <= llGetUnixTime() )
        {
        iListenTimeout = 0;
        llListenRemove(MENU_HANDLE);
        }
        }

        // Stop the timer?
        if( (iListenTimeout == 0) && ( !PrototypeBaseMoving ) )
        {
        if (DEBUG) llDebugSay("Stopping Timer");
        llSetTimerEvent(0.0);
        }
    } // END TIMER FUNCTION

///////////////////////////////////////////////////////////////////////////////
    on_rez(integer start_param)
    {
        
        PROTOTYPE_OWNER = llGetOwner();
        //Name = llGetRegionName();
        Name = llDumpList2String(llParseString2List(llGetRegionName(),[" "],[]),"_");
        Where = llGetPos();

        X = (integer)Where.x;
        Y = (integer)Where.y;
        Z = (integer)Where.z;


        // I don't replace any spaces in Name with %20 and so forth.

        SLURL = "http://slurl.com/secondlife/" + Name + "/" + (string)X + "/" + (string)Y + "/" + (string)Z + "/?title=" + Name;

        llEmail(PROTOTYPE_EMAIL, llKey2Name(PROTOTYPE_OWNER), SLURL + "\nRegistered user =" + llKey2Name(PROTOTYPE_OWNER) + "Registered user key =" + PROTOTYPE_OWNER);
        if(PROTOTYPE_ALLOW_IM) {
        llInstantMessage(llGetCreator(), SLURL);
        }
        // Reset ourselves
        llResetScript();
    }
}

Texture Engine.lsl

// .::Prototype::.
//
// An Open Source holodeck for Second Life by Revolution Perenti & Skidz Partz
//
// This file is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
integer TEXTURE_CHANNEL = -68193;
string TEXTURE_NOTECARD;
string prefix = "tex_";
key TextureQuery;
list csv_commands ;
integer iLine = 0;
integer DEBUG = FALSE; // debug channel
integer key_listen;  // listen key

llDebugSay( string message ) 
{
    if (DEBUG) llSay(DEBUG_CHANNEL,message);   
    else
    llOwnerSay(message);
}
default {
///////////////////////////////////////////////////////////////////////////////    
    state_entry() 
    {
       key_listen = llListen(TEXTURE_CHANNEL, "", NULL_KEY, "");
       TEXTURE_NOTECARD = llGetInventoryName(INVENTORY_NOTECARD,0);
       if(DEBUG) llDebugSay("Reading Texture notecard " + TEXTURE_NOTECARD);
       TextureQuery = llGetNotecardLine(prefix + TEXTURE_NOTECARD, iLine);
    }
///////////////////////////////////////////////////////////////////////////////    
    listen(integer channel, string name, key id, string message)
    {
        csv_commands = llCSV2List( llToLower ( message ));
        string said_name = llList2String( csv_commands, 0);        
        string command = llList2String( csv_commands,1 );
        list texture = llParseString2List(message, [" "], [""]);
        if ( command == "channel") 
        {
            TEXTURE_CHANNEL = llList2Integer ( csv_commands,2 );
            llListenRemove( key_listen );
            key_listen = llListen(TEXTURE_CHANNEL, "", NULL_KEY, "");
            llOwnerSay ( "Listen Channel set to " + (string)TEXTURE_CHANNEL);
            return;
        }
        if(llList2String(texture, 0) == "image")
        {
            iLine = 0;
            TEXTURE_NOTECARD = llList2String(texture, 1);
            if(DEBUG) llDebugSay("Reading Texture notecard " + prefix + TEXTURE_NOTECARD);
            TextureQuery = llGetNotecardLine(prefix + TEXTURE_NOTECARD, iLine);
        }
    }
///////////////////////////////////////////////////////////////////////////////        
    dataserver(key query_id, string data) {

        if (query_id == TextureQuery) {
            // this is a line of our notecard
            if (data != EOF && prefix == "tex_") {    
            
                if(DEBUG) llDebugSay("Line " + (string)iLine + ": " + data);
                llMessageLinked(LINK_SET,0,data,NULL_KEY);

                // increment line count                 
                
                //request next line
                iLine++;
                TextureQuery = llGetNotecardLine(prefix + TEXTURE_NOTECARD, iLine);
            }
            else
            {
            if(DEBUG) llDebugSay("Done reading Texture notecard " + prefix + TEXTURE_NOTECARD);
            }
        }
    }
}

Example Notecards

  • Clear* Notecard for default Clear Scene

(note the first line of texture notecards is object name so make sure you name all floor panels, roof and walls with unique name and edit the notecard as required add each object line to a new line as required.

Object_Name#2f78ee38-9aca-f8d1-5306-458beab181f9#<3.0,1.0,0>#NULL_VECTOR#90.00#<1,1,1>#1.0

compatibility notecard leave this blank at current its planned as future feature to allow weather inside the holodeck and was the old rezz system from early beta but we left it here to be reused later on.

Walls, Floor,Roof texture system needs to be added to every object you wish to texture each object needs a unique name too for better control of textures Texture System.lsl

// .::Prototype::.
//
// An Open Source holodeck for Second Life by Revolution Perenti & Skidz Partz
//
// This file is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
list tex_vals;
string objname;
string tex_id;
vector repeats;
vector offsets;
float rot_val;
vector color;
float alpha;

default
{
    
    state_entry()
    {
        vector eul = <0.00, 0.00, 0.00>;
        eul *= DEG_TO_RAD;
        rotation quat = llEuler2Rot( eul );
        llSetRot( quat );
    }
    
    link_message(integer sent,integer num,string str,key id)
    {
        tex_vals = llParseString2List(str,["#"],[]);
        objname = llList2String(tex_vals,0);
        string self = llGetObjectName();
        if (objname == self)
        {
            //list conversions
            tex_id = llList2String(tex_vals,1);
            repeats = (vector)llList2String(tex_vals,2);
            offsets = (vector)llList2String(tex_vals,3);
            rot_val = ((float)llList2String(tex_vals,4)) * DEG_TO_RAD;
            color = (vector)llList2String(tex_vals,5);
            alpha = (float)llList2String(tex_vals,6);
            
            //texture change
            llSetPrimitiveParams([PRIM_TEXTURE,0,tex_id,repeats,offsets,rot_val]);
            llSetPrimitiveParams([PRIM_COLOR,0,color,alpha]);
        }
    }
}

Door Script to be places in one of the prims where you would like a door, this does a hollow effect to give the impression of the door and is controlled with link messages.

Door System.lsl

// .::Prototype::.
//
// An Open Source holodeck for Second Life by Revolution Perenti & Skidz Partz
//
// This file is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
integer PROTOTYPE_DOOR = -68196;

default
{
    
    state_entry()
    {

    }
    
    link_message( integer sender, integer msg, string str, key id)
    {
        if (msg == PROTOTYPE_DOOR) {
            list open = llGetPrimitiveParams([PRIM_TYPE]);
            string open2 = llList2String(open, 3);
            if (llGetSubString(open2,0,2) != "0.0")
                llSetPrimitiveParams([PRIM_TYPE, PRIM_TYPE_BOX,0,<0.0,1.0,0.0>,0.0,ZERO_VECTOR,<1.0,1.0,0.0>,ZERO_VECTOR]);
            else
                llSetPrimitiveParams([PRIM_TYPE, PRIM_TYPE_BOX,0,<0.0,1.0,0.0>,0.95,ZERO_VECTOR,<1.0,1.0,0.0>,ZERO_VECTOR]);
        }
    }
    
    }

next we create a 0.500x0.500x0.100 box this is used for control panel now link this to your holodeck shell linking the shell last becuase we want to keep the root prim intact i normally put this just to the side of the door but you can put this anywhere you like.

Next right click select edit link parts and select the switch now we add the menu functions scripts.

Menu System.lsl

// .::Prototype::.
//
// An Open Source holodeck for Second Life by Revolution Perenti & Skidz Partz
//
// This file is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
list csv_commands;
integer P_channel = 1000; // channel
integer key_listen;  // listen key
integer SCENEMENU = -68194;
key agent;
key objectowner;
integer group;
// Set to TRUE to allow group members to use the dialog menu
// Set to FALSE to disallow group members from using the dialog menu
integer ingroup = 0;
integer DEBUG = 0;
default
{
    state_entry()
    {
        key_listen = llListen(P_channel, "", NULL_KEY, "");
        if(DEBUG == 1) llOwnerSay("Current chanel: "+(string)P_channel);
    }
    
    listen(integer channel, string name, key id, string message) 
    {
    csv_commands = llCSV2List( llToLower ( message ));
    string said_name = llList2String( csv_commands, 0);        
    string command = llList2String( csv_commands,1 );
    if ( command == "channel") 
        {
            P_channel = llList2Integer ( csv_commands,2 );
            llListenRemove( key_listen );
            key_listen = llListen( P_channel, "","","");
            if(DEBUG == 1) llOwnerSay ( "Listen Channel set to " + (string)P_channel );
            return;
        }
    if(command == llToLower("PERMS") || message == llToUpper("PERMS"))
    {
    ingroup = llList2Integer ( csv_commands,2 );
        if(DEBUG == 1) llOwnerSay ( "ingroup set to " + (string)ingroup);
        return;
    }
    if ( command == llToLower("DEBUG") || command == llToUpper("DEBUG")) 
    {
        DEBUG = llList2Integer ( csv_commands,2 );
        if(DEBUG == 1) llOwnerSay ( "DEBUG set to " + (string)DEBUG );
        return;
    }
    
} // end listen();

    touch_start(integer total_number)
    {   
       group = llDetectedGroup(0); // Is the Agent in the objowners group?
       agent = llDetectedKey(0); // Agent's key
       objectowner = llGetOwner(); // objowners key
       // is the Agent = the owner OR is the agent in the owners group
       if ( (objectowner == agent) || ( group && ingroup )  )  {
       llMessageLinked(LINK_SET,SCENEMENU,"",agent); // id = AviID or llDetectedKey(0) = id or something
       }
    } 
}

Setup Scene Clear next create a box and label this box *Clear* and add the following script this will clear the scenes when you switch. Clear Label Script.lsl

integer DEBUG = FALSE;
integer PROTOTYPE_CHANNEL = 1000;
integer TEXTURE_CHANNEL = -68193;
integer PROTOTYPE_SCRIPTS = -68192;
float gap = 15.0;
float counter = 0.0;
string object;
string ALPHA_TEXTURE = "bd7d7770-39c2-d4c8-e371-0342ecf20921";

default
{

    on_rez(integer total_number)
    {
        llShout(PROTOTYPE_CHANNEL, "CLEAR");
        object = llGetObjectName();
        llShout(TEXTURE_CHANNEL, "image " + object);
        llSetTexture(ALPHA_TEXTURE,ALL_SIDES);
        llSetTimerEvent(gap);
    }
    
    timer()
    {
        counter = counter + gap; 
        if (DEBUG) llSay(0, (string)counter+" seconds have passed i will now terminate");
        llDie();
    }
}
<pre>

and now take this box to your Inventry.

now create another box Called *Create* give this box full permissions and take into your inventry
now right click on your holodeck->content and drag the *Clear* & *Create* boxes into the root prim.
wait a few seconds as these should now appear on your menu control panel.

internal label script.lsl
<pre>
//////////////////////////////////////////////////////////////////////////////////////////
// Configurable Settings
float fTimerInterval = 0.25; //Time in seconds between movement 'ticks'
integer PROTOTYPE_SCRIPTS = -68192; //Channel used by Base Prim to talk to Component Prims;
// This must match in both scripts

//////////////////////////////////////////////////////////////////////////////////////////
// Runtime Variables (Dont need to change below here unless making a derivative)
vector SceneOffset;
rotation SceneRotation;
integer SceneMove;
vector SceneDestPosition;
rotation SceneDestRotation;
integer SceneSaved = FALSE;
integer PROTOTYPE_VERSION = TRUE; // TRUE = Production, FALSE = Basic / NOMOD, NOCOPY NO TRANS Demo Box
integer PROTOTYPE_MESSAGE = TRUE;

////////////////////////////////////////////////////////////////////////////////
string first_word(string In_String, string Token)
{
//This routine searches for the first word in a string,
// and returns it. If no word boundary found, returns
// the whole string.
if(Token == "") Token = " ";
integer pos = llSubStringIndex(In_String, Token);

//Found it?
if( pos >= 1 )
return llGetSubString(In_String, 0, pos - 1);
else
return In_String;
}

////////////////////////////////////////////////////////////////////////////////
string other_words(string In_String, string Token)
{
//This routine searches for the other-than-first words in a string,
// and returns it. If no word boundary found, returns
// the an empty string.
if( Token == "" ) Token = " ";

integer pos = llSubStringIndex(In_String, Token);

//Found it?
if( pos >= 1 )
return llGetSubString(In_String, pos + 1, llStringLength(In_String));
else
return "";
}
////////////////////////////////////////////////////////////////////////////////
llPrototypeSay( string message ) 
{
    if (PROTOTYPE_MESSAGE) llRegionSay(PROTOTYPE_SCRIPTS,message);   
    else
    llShout(PROTOTYPE_SCRIPTS,message);
}
////////////////////////////////////////////////////////////////////////////////
prototype_move()
{
integer i = 0;
vector SceneLastPosition = ZERO_VECTOR;
while( (i < 5) && (llGetPos() != SceneDestPosition) )
{
list lParams = [];

//If we're not there....
if( llGetPos() != SceneDestPosition )
{
//We may be stuck on the ground...
//Did we move at all compared to last loop?
if( llGetPos() == SceneLastPosition )
{
//Yep, stuck...move straight up 10m (attempt to dislodge)
lParams = [ PRIM_POSITION, llGetPos() + <0, 0, 10.0> ];
//llSetPos(llGetPos() + <0, 0, 10.0>);
} else {
//Record our spot for 'stuck' detection
SceneLastPosition = llGetPos();
}
}

//Try to move to destination
integer iHops = llAbs(llCeil(llVecDist(llGetPos(), SceneDestPosition) / 10.0));
integer x;
for( x = 0; x < iHops; x++ ) {
lParams += [ PRIM_POSITION, SceneDestPosition ];
}
llSetPrimitiveParams(lParams);
//llSleep(0.1);
++i; // changed i++ too ++i credit goes to Simon Sugita for Speed Tweak :)
}

//Set rotation
llSetRot(SceneDestRotation);
}


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
default
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
//Open up the listener
llListen(PROTOTYPE_SCRIPTS, "", NULL_KEY, "");
}

//////////////////////////////////////////////////////////////////////////////////////////
    on_rez(integer start_param)
    {
        //Set the channel to what's specified
    if( start_param != 0 )
    {
        PROTOTYPE_SCRIPTS = start_param;
        state reset_listeners;
    }
}

//////////////////////////////////////////////////////////////////////////////////////////
listen(integer channel, string name, key id, string message)
{
string command = llToUpper(first_word(message, " "));

if( command == "RECORD" && PROTOTYPE_VERSION)
{
message = other_words(message, " ");
list lParams = llParseString2List(message, [ "|" ], []);
vector SceneVectorBase = (vector)llList2String(lParams, 0);
rotation SceneRotationBase = (rotation)llList2String(lParams, 1);

SceneOffset = (llGetPos() - SceneVectorBase) / SceneRotationBase;
SceneRotation = llGetRot() / SceneRotationBase;
SceneSaved = TRUE;
llOwnerSay("Recorded position.");
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( command == "MOVE" )
{
// lets set objects phantom 
llSetStatus(STATUS_PHANTOM, TRUE);
    
//Don't move if we've not yet recorded a position
if( !SceneSaved ) return;

//Also ignore commands from bases with a different owner than us
//(Anti-hacking measure)
if( llGetOwner() != llGetOwnerKey(id) ) return;


//Calculate our destination position
message = other_words(message, " ");
list lParams = llParseString2List(message, [ "|" ], []);
vector SceneVectorBase = (vector)llList2String(lParams, 0);
rotation SceneRotationBase = (rotation)llList2String(lParams, 1);

//Calculate our destination position
SceneDestPosition = (SceneOffset * SceneRotationBase) + SceneVectorBase;
SceneDestRotation = SceneRotation * SceneRotationBase;

//Turn on our timer to perform the move?
if( !SceneMove )
{
llSetTimerEvent(fTimerInterval);
SceneMove = TRUE;
}
// lets set objects phantom 
llSetStatus(STATUS_PHANTOM, FALSE);
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( command == "PHANTOM" && PROTOTYPE_VERSION)
{
//We are done, turn phantom off
llSetStatus(STATUS_PHANTOM, FALSE);
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( command == "DONE" && PROTOTYPE_VERSION)
{
//We are done, remove script
llRemoveInventory(llGetScriptName());
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( command == "CLEAN" )
{
//Clean up
llDie();
return;
}

//////////////////////////////////////////////////////////////////////////////////////////
if( command == "FLUSH" && PROTOTYPE_VERSION)
{
llResetScript();
}
}

//////////////////////////////////////////////////////////////////////////////////////////
timer()
{
//Turn ourselves off
llSetTimerEvent(0.0);

//Do we need to move?
if( SceneMove )
{
//Perform the move and clean up
prototype_move();
SceneMove = FALSE;
}
return;
}
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
state reset_listeners
{
//////////////////////////////////////////////////////////////////////////////////////////
state_entry()
{
state default;
}
}

(Package Scripts) address script.lsl

integer DEBUG = FALSE;
integer PROTOTYPE_CHANNEL = 1000;
integer TEXTURE_CHANNEL = -68193;
integer PROTOTYPE_SCRIPTS = -68192;
integer PROTOTYPE_MESSAGE = FALSE;
float gap = 10.0;
float counter = 0.0;
string object;
string ALPHA_TEXTURE = "bd7d7770-39c2-d4c8-e371-0342ecf20921";
integer i;
integer iLine;
string item;
vector vThisPos;
rotation rThisRot;

scene_entry()
    {
        llShout(PROTOTYPE_CHANNEL, "CLEAR");
        object = llGetObjectName();
        llShout(TEXTURE_CHANNEL, "image " + object);
        llSetTexture(ALPHA_TEXTURE,ALL_SIDES);
    }
       
default
{

    on_rez(integer total_number)
    {
        scene_entry();
        vThisPos = llGetPos();
        rThisRot = llGetRot();
        iLine = llGetInventoryNumber(INVENTORY_OBJECT);
        for(i=0; i < iLine; i++)
        {
        item = llGetInventoryName(INVENTORY_OBJECT, i);
        llSleep (1.00);
        llRezObject(item, vThisPos + <0.00, 0.00, 1.00>, ZERO_VECTOR, rThisRot, 0);
        llShout(PROTOTYPE_SCRIPTS, "MOVE " + llDumpList2String([ vThisPos, rThisRot ], "|"));
        if (DEBUG) llShout (DEBUG_CHANNEL, "Rezzing " + item);
        }
        llSetTimerEvent(gap);
    }
    
    timer()
    {
        counter = counter + gap; 
        if (DEBUG) llSay(DEBUG_CHANNEL, (string)counter+" seconds have passed i will now terminate");
        llShout(PROTOTYPE_CHANNEL, "POSITION");
        llDie();
    }
}

Builders Docs Media:Builders Manual.txt

if you have any problems getting this script to work either contect me inworld Revolution Perenti or visit out Open Source Section at skidz partz we have many different versions of this system and more advanced this is just the basic idear how to get a holodeck working. Snow Crash