Sheena Desade's Sim-to-Sim Teleporter Script and Notecard (v3.1). Includes dynamic smart menu and instant teleportation (no confirmation required) via chat link. Missing sanity checks, so format things correctly! Public domain (open-source) since April 10, 2012.
See http://www.free-lsl-scripts.com/cgi/freescripts.plx?ID=1651 for an updated version by Donjr Spiegelblatt
This is Sheena Desade's Sim-to-Sim Teleporter Script (v3.1).
Features/Pros:
Smart Menu - seamlessly cycles, rearranges buttons in a logical order.
Dynamic List Parsing - never worry about breaking the script by adding or removing a location.
Instant Teleportation (no confirmation required!) via chat link (visit http://wiki.secondlife.com/wiki/Viewer_URI_Name_Space for more nifty links you can add to your own products).
Add as many locations as the script's memory can hold!
Missing/Cons:
Sanity checks! Format things correctly, or it will break.
Private chat - this says everything on channel zero for everyone to hear (does not use llRegionSayTo).
Annoying notecard configuration.
The sim/place names/location vectors lists could have been combined into one to save a little more memory.
---------
'Data' notecard:
Hover_Text = Multi-Region Pseudo Teleporter: Click for Destinations
Menu_Text = Please select your destination:
Menu_Channel = 4765
Selection_Wait_Time = 30.0
Niamhinations! | Windlesham @ 207/580/133
---------
(template for the locations: Company Name | Region Name @ location x/location y/location z)
// Script Name: Sim-to-Sim_Pseudo-Teleporter_v31.lsl
// Author: Sheena Desade
// Sheena Desade's Sim-to-Sim Teleporter Script and Notecard (v3.1). Includes dynamic smart menu and instant teleportation (no confirmation required) via chat link. Missing sanity checks, so format things correctly! Public domain (open-source) since April 10, 2012.
//
//See http://www.free-lsl-scripts.com/cgi/freescripts.plx?ID=1651 for an updated version by Donjr Spiegelblatt
// Downloaded from : http://www.free-lsl-scripts.com/cgi/freescripts.plx?ID=1646
// This program is free software; you can redistribute it and/or modify it.
// Additional Licenes may apply that prevent you from selling this code
// You must leave any author credits and any headers intact in any script you use or publish.
///////////////////////////////////////////////////////////////////////////////////////////////////
// If you don't like these restrictions and licenses, then don't use these scripts.
//////////////////////// ORIGINAL AUTHORS CODE BEGINS ////////////////////////////////////////////
// This is Sheena Desade's Sim-to-Sim Teleporter Script (v3.1).
//
//Features/Pros:
//Smart Menu - seamlessly cycles, rearranges buttons in a logical order.
//Dynamic List Parsing - never worry about breaking the script by adding or removing a location.
//Instant Teleportation (no confirmation required!) via chat link (visit http://wiki.secondlife.com/wiki/Viewer_URI_Name_Space for more nifty links you can add to your own products).
//Add as many locations as the script's memory can hold!
//
//Missing/Cons:
//Sanity checks! Format things correctly, or it will break.
//Private chat - this says everything on channel zero for everyone to hear (does not use llRegionSayTo).
//Annoying notecard configuration.
//The sim/place names/location vectors lists could have been combined into one to save a little more memory.
//
//---------
//'Data' notecard:
//
//Hover_Text = Multi-Region Pseudo Teleporter: Click for Destinations
//Menu_Text = Please select your destination:
//Menu_Channel = 4765
//Selection_Wait_Time = 30.0
//Niamhinations! | Windlesham @ 207/580/133
//---------
//
//(template for the locations: Company Name | Region Name @ location x/location y/location z)
/*
This script was made April 10, 2012 by Sheena Desade. It is meant only to be redistributed freely (not ever to be sold)! Leave this header intact; other than those two requirements, do what you will with it. And if you make an improvement, feel free to send me a copy. :-)
*/
// ******** OPTIONAL SETTINGS **********
string hoverText = "Sim-to-Sim Pseudo Teleporter - click for destinations.";
float menuWait = 30.0; // How long to wait for the user to pick a menu choice
integer menuChannel = 0; // what channel for the object to 'listen' on. You can change this channel as needed,
// it's not calling out to an object outside of itself.
string menuText = "Please select your destination:";
string itemDataNotecard = "Data";
// The name of the notecard to read from
// ******** END OF OPTIONAL SETTINGS **********
// ******** SYSTEM SETTINGS - DO NOT MODIFY **********
// General variables
integer menu_handler; // what the function that brings up the menu is called
integer loc = -1; // -1 = none chosen; 0 = first location, etc.
integer length; // How long the placeNames list is, which we base everything else off of
integer curList = 1; // The current list number we're on
key curUser = NULL_KEY; // The current user's key
// The following are required to read the notecard properly
integer notecardLine;
key currentDataRequest;
key notecarduuid;
// These are the lists that hold all of our information
list simNames; // The sim names of the places to teleport to
list placeNames; // The region names of the places to teleport to
list locationVectors; // The position to teleport to
// ******** END OF SYSTEM SETTINGS **********
init() // Setup the dataserver event for future use
{
llOwnerSay("Reading item data...");
notecardLine = 0; // we start reading the notecard at line 0, the first line
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine); // specify our initial request
}
advancedMenu(key user, string text, integer channel)
{
menu_handler = llListen(menuChannel,"","",""); // Lets the object 'hear' the option you choose
if (length <= 12) llDialog(user,text,placeNames,channel); // Brings up a simple dialog if you have 12 or less options.
else // If we have more than 12 options, create a multi-page dialog
{
list buttons; // Makes a list called 'buttons' that we will use later
if (curList >= 1) // If we are not on page 0 (shouldn't be possible)
{
integer temp = (9*curList)-1; // Figures out which locations to display as buttons
buttons = llList2List(placeNames, temp-8, temp); // the 'buttons' list now has nine locations
// (List2List starts at 0, so we count 0 as 1)
buttons = llListInsertList(buttons, ["><< Prev", "Cancel", "Next >>"], temp+1);
// the 'buttons' list also now has three other options besides our nine locations
// (ListInsertList does NOT start at 0. It starts at 1.)
}
buttons =
llList2List(buttons, -3, -1)
+ llList2List(buttons, -6, -4)
+ llList2List(buttons, -9, -7)
+ llList2List(buttons, -12, -10); // Puts our buttons in the logical order, instead of the default reversed one
llDialog(user,text,buttons,channel); // Sends a dialog to the user with the new improved button list
}
}
default
{
on_rez(integer param)
{
llResetScript(); // Resets script on rez
}
state_entry()
{
llOwnerSay("Initializing...");
notecarduuid = llGetInventoryKey(itemDataNotecard); // collects our notecarduuid as soon as we enter this state
init(); // runs our init function to use with our dataserver function
}
dataserver(key query, string data)
{
if (query == currentDataRequest) // if we are trying to read the notecard
{
currentDataRequest = ""; // Prevent a bug that occurs with dataserver events.
if (data != EOF) // If it isn't the end of the file
// **** IMPORTANT: I did not put any sanity checks in here, so you'll need to type
// it all correctly, in the format "Store Name | Sim Name @ x/y/z" or it will not
// work correctly! ****
{
integer s = llSubStringIndex(data, "@"); // We're looking for the @ symbol in our NC line
if(~s) // If we find it
{
string data1 = llStringTrim(llDeleteSubString(data, s, -1), STRING_TRIM);
// this line cuts out and saves everything before the @ symbol to use for the next index
string data4 = llStringTrim(llDeleteSubString(data, 0, s), STRING_TRIM);
// this line erases the @ symbol and temporarily saves the location into a seperate string
integer s = llSubStringIndex(data1, "|"); // Now we're looking for the pipe symbol in only the
// 'data1' variable defined when we were parsing for the @ symbol
if(~s) // If we find it (which we should, but we will check later to make sure our lists are
// the same length, anyway)
{
string data2 = llDumpList2String(llParseString2List(llStringTrim(llDeleteSubString(data1, 0, s), STRING_TRIM), [" "], [""]), "%20");
// Saves the first part in a temp string, erasing all spaces and replacing them with %20... there might be a better way to do this
string data3 = llStringTrim(llDeleteSubString(data1, s, -1), STRING_TRIM);
// Saves the second part in a temp string
simNames += [data2];
// copies the temporary string data2 into our simNames list. Could probably combine the two
// commands as with locationVectors.
placeNames += [data3];
// copies the temporary string data3 into our placeNames list. Could probably combine the
// two commands, as with locationVectors and simNames.
locationVectors += [data4];
// this line copies the temporary string into our locationVectors list. We put it here so that it
// will not add the locationVector unless there are also sim and placeNames.
}
}
else
{
integer s = llSubStringIndex(data, "="); // Now we are looking for the = symbol
if(~s) // if we find it
{
string token = llToLower(llStringTrim(llDeleteSubString(data, s, -1), STRING_TRIM));
// use our tokens to determine which variable we are defining
data = llStringTrim(llDeleteSubString(data, 0, s), STRING_TRIM);
// use our data to define our chosen variable
if (token == "hover_text")
hoverText = data;
else if (token == "menu_text")
menuText = data;
else if (token == "menu_channel")
menuChannel = (integer)data;
else if (token == "selection_wait_time")
menuWait = (float)data;
}
}
notecardLine++;
// Get the next line
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
}
else // If it is the End of File
{
length = llGetListLength(placeNames); // Defines how many entries we have in the placeNames list
llOwnerSay ("Done reading data.");
state configured;
}
}
}
}
state configured
{
state_entry()
{
if (hoverText != "none") llSetText(hoverText, <1 .0,1.0,1.0>, 1); // if you want hovertext
if (hoverText == "none") llSetText("---", 1><1 .0, 1.0, 1.0>, 0); // if you do not want hovertext
llWhisper(0, "Ready and waiting.");
loc = -1; // Resets the location to none
}
changed(integer change)
{
// We want to reload channel notecard if it changed
if (change & CHANGED_INVENTORY)
{
if(notecarduuid != llGetInventoryKey(itemDataNotecard)) // If the change was triggered by saving the NC
{
llOwnerSay("Notecard change detected, resetting script.");
llResetScript(); // resets the script
}
}
}
timer()
{
llListenRemove(menu_handler); // remove the listen event
llInstantMessage(curUser, "Menu session timed out; choices automatically reset.");
llSetTimerEvent(0.0); // removes the timer event, as it's not needed at the moment
curList = 1; // reset our page to page one
loc = -1; // set our location to none
curUser = NULL_KEY; // resets the user to none
}
touch_start(integer total_number)
{
if(curUser == NULL_KEY || curUser == llDetectedKey(0)) // if there is no user or the toucher is the
// current user
{
curUser = llDetectedKey(0); // records the key of the curent user
advancedMenu(curUser, menuText, menuChannel); // Sends the user our dialog box
llSetTimerEvent(menuWait); // Sets our timer event so the menu will time out
}
if(curUser != NULL_KEY && curUser != llDetectedKey(0)) // If the toucher is not the current user
llInstantMessage(llDetectedKey(0), "Sorry, this terminal is in use. Please wait your turn.");
}
listen(integer channel,string name,key id,string message)
//this is for the script to follow instructions based on what happens with the menu.
{
if(message == "<< Prev")
{
if(curList <= 1) // If we're on the first page
{
curList = llCeil((float)length/9); // the current page needs to be changed to the last page, since
// we're cycling backwards. We do this by rounding up (to cover any remainders) the length variable
// (how many options we have total) divided by nine (since that's the number of buttons we need). 4.000
// will always round up to 4 (I think?).
advancedMenu(curUser, menuText, menuChannel); // Give them our menu dialog
llSetTimerEvent(menuWait); // how long until the menu times out?
}
else // If we're not on page one
{
curList--; // Go backwards a page
advancedMenu(curUser, menuText, menuChannel); // Give them our menu dialog
llSetTimerEvent(menuWait); // how long until the menu times out?
}
}
else if(message == "Next >>")
{
if(curList*9 >= length) // if we have cycled through all options in our list
{
curList = 1; // go to page one
advancedMenu(curUser, menuText, menuChannel); // Give the user our dialog menu
llSetTimerEvent(menuWait); // how long until the menu times out?
}
else
{
curList++; // go to the next page
advancedMenu(curUser, menuText, menuChannel); // Give the user our dialog menu
llSetTimerEvent(menuWait); // how long until the menu times out?
}
}
else if(message == "Cancel")
{
llInstantMessage(curUser, "Teleport cancelled.");
curUser = NULL_KEY; // Erase the current user
curList = 1; // Put our page back on the first page
llListenRemove(menu_handler); // remove our listen event
llSetTimerEvent(0.0); //removes the timer event, as it's not needed at the moment
}
else
{
loc = llListFindList(placeNames, (list)message); // determine which location we are teleporting to
if(loc >= 0) // if it's an actual location
{
if (hoverText != "none") llSetText("Click the link to teleport", <1 .0,1.0,1.0>, 1);
// if you want hovertext
llInstantMessage(curUser, "Click this link to teleport to your target location - " + "secondlife:///app/teleport/" + llList2String(simNames, loc) + "/" + llList2String(locationVectors, loc)); // Give them the link to click
llSetTimerEvent(0.0); // removes the timer event, as it's not needed at the moment
llSleep(2.5);
curUser = NULL_KEY; // resets our user so others can use the teleporter
loc = -1; // reset our location to none
curList = 1; // reset our page to one
if (hoverText != "none") llSetText(hoverText, 1><1 .0,1.0,1.0>, 1);
}
}
}
}
1>>1>>