Difference between revisions of "Holodeck"
(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
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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
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
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