Jump to content
Hillary Davi

LSL Experience Teleporter

Recommended Posts

The first post just wanted to share some code to create an experience teleporter. If you feel you can make it better please post it here.

The variables on top

teleportme is where you want to go on the sim

textdefault is the title over head which will automatically be changed and reset 

I used and read the following articles, Please read the following to understand the code

  1. http://wiki.secondlife.com/wiki/LlAgentInExperience
  2. https://wiki.secondlife.com/wiki/LlRequestExperiencePermissions
  3. https://wiki.secondlife.com/wiki/LlGetExperienceErrorMessage
vector teleportme = <212,150,1000>;
string MyObjectName;
string textdefault = "Teleport to platform!";
//Begin code
string theerror;
integer error;
key agent;
integer type;
default
{
    state_entry()
    {
        MyObjectName = llGetObjectName();
        llVolumeDetect(TRUE);
        llSetText(textdefault, <1.0, 1.0, 1.0>, 1.0);
    }
    collision_start(integer num)
    { 
       agent = llDetectedKey(0); type = llDetectedType(0);
       if (type == (AGENT | ACTIVE) ) // 1 + 2
        {
            llRequestExperiencePermissions(agent, "");
        }   
    } 
    experience_permissions(key agent) {
            llSetText(llKey2Name(agent) + " is using the teleporter please wait...", <1.0, 1.0, 1.0>, 1.0);
            llTeleportAgent(agent, "", teleportme, teleportme);
            llSleep(1);
             llSetText(textdefault, <1.0, 1.0, 1.0>, 1.0);   
    }
    
    experience_permissions_denied(key agent, integer reason){
        string theerror = llGetExperienceErrorMessage((integer)reason);
        if(reason = XP_ERROR_THROTTLED) {
         llSleep(2);
        } else if (reason = XP_ERROR_REQUEST_PERM_TIMEOUT || reason = XP_ERROR_NOT_PERMITTED || reason = XP_ERROR_NOT_FOUND) {
             llInstantMessage(agent, "Please accept the experience or bad things may happen!"); 
            } 
        if(!llAgentInExperience(agent)) {
         llRequestExperiencePermissions(agent, "");  
         //llRequestExperiencePermissions(llDetectedKey(0), "");
        }
       
    }
    
    touch_start(integer total_number)
    {
     agent = llDetectedKey(0);  type = llDetectedType(0);
       if (type == (AGENT | ACTIVE) ) // 1 + 2
        {
            llRequestExperiencePermissions(agent, "");
        } 
    }
     
}
    

 

  • Thanks 1

Share this post


Link to post
Share on other sites

Looks good, but one question -- why are you using the same vector, teleportme, for both the destination and the look_at vector?   In which direction does <212,150,1000> mean you should look?   

Share this post


Link to post
Share on other sites

Not sure did not look into that function deeply but I know it works. 

Edit- I remember now I think one vector is the location and the other is the offset. I set it this way because if i wanted i can make another variable and change it up quickly. Not sure it's the proper but a nice placeholder. ;)

Edit2: The other is vector look at. http://wiki.secondlife.com/wiki/LlTeleportAgent

Function: llTeleportAgent( key avatar, string landmark, vector position, vector look_at );

Edited by Hillary Davi
update

Share this post


Link to post
Share on other sites

That vector is the position that your teleportee is intended to be facing as she arrives.  It's a global vector, not local relative to the avatar. The Z component is ignored, since an avatar is always vertical. If you use the same vector for both the destination and the LookAt position, I think the default is that you end up facing east. Frankly, I've never tried doing that, but it makes sense.

Elsewhere in the script, I can't think of a situation where it's necessary to specify that an AGENT is also ACTIVE.  Certainly not in teleportation.  You could simplify the script by removing that condition.

Edited by Rolig Loon

Share this post


Link to post
Share on other sites
if(reason = XP_ERROR_THROTTLED) {
         llSleep(2);
        } else if (reason = XP_ERROR_REQUEST_PERM_TIMEOUT || reason = XP_ERROR_NOT_PERMITTED || reason = XP_ERROR_NOT_FOUND)

You're assigning (=) constants instead of evaluating (==) them. And in regards to the errors you're checking,

XP_ERROR_THROTTLED is a KVP throttle error, not a teleport throttle error. The tp throttle is in the form of a script error.

XP_ERROR_REQUEST_PERM_TIMEOUT occurs after 5 minutes of no acknowledgement from the user for perms request.

XP_ERROR_NOT_FOUND is an experience not found server error, not an agent not found error.

The most common errors to occur are XP_ERROR_NOT_PERMITTED with agents blocking or already having blocked the experience and XP_ERROR_NOT_PERMITTED_LAND where the target agent or host object is not over land that has the experience allowed.

 

        if(!llAgentInExperience(agent)) {
         llRequestExperiencePermissions(agent, "");  
         //llRequestExperiencePermissions(llDetectedKey(0), "");
        }

You shouldn't re-request perms inside the exp perms denied event or you will most likely just end up continuously triggering it regardless of the error.

  • Like 1

Share this post


Link to post
Share on other sites
13 minutes ago, villadelfia said:

I don't see the point of sleeping for 1 second upon teleporting someone.

There is sometimes a good reason for putting a llSleep in a teleporter, to avoid running into the region's throttle.  That's not likely to be a problem unless you have a lot of teleporters, or a single teleporter that is designed to TP a crowd of people in a very short time, but it could make sense then.

Edited by Rolig Loon

Share this post


Link to post
Share on other sites

First, I put the second sleep because I kept getting errors when people touched it continuously. You probably don't need it so comment it out ;D All you need to do is add the // to the line.

every time someone calls the touch I also had it do another sleep. The seconds are so small I just figured to keep it there. As the delay was not noticeable. Pick the sleep and just comment out if you don't need. 

experience_permissions_denied( //Added the test and check if there was a throttle

 

Share this post


Link to post
Share on other sites
53 minutes ago, Hillary Davi said:

I put the second sleep because I kept getting errors when people touched it continuously.

That's a very good reason. If people are spam clicking the teleporter, you will indeed hit the region throttle and get an error message. IMO, though, it would be smarter to prevent spam clicking in the first place.  All you need is a global integer (iTouched) that you can use as a flag to flip as soon as someone clicks, and then flip back after the teleport is complete.
 

touch_start (integer num)
{
    if (!iTouched)
    {
        iTouched = TRUE;
        // Do your TP stuff
        llSetTimerEvent(1.0);    // Here's your substitute for a llSleep
    }
}

timer()
{
    llSetTimerEvent(0.0);
    iTouched = FALSE;
}

Then you can get rid of your check for ERROR_THROTTLED and simplify the script.  (In fact, I would remove the entire experience_permissions_denied event, but that's me.)

Share this post


Link to post
Share on other sites

Another way to prevent spam clicking would be something like 

	touch_start(integer total_number)
	{
		if(llGetTime()> 1.0){
			llResetTime();
			//do teleporter stuff
		}
	}

 

Share this post


Link to post
Share on other sites

Thanks to everyone who contributed this is what I Have in the sorta final.

I liked the switch idea by Rolig Loon because it allowed reusing the timer since you can only have one timer in a state. Although I still get errors it might be due to the error checking. I am rethinking the are where Lucia Nightfire posted about.

Lines: 60 61 and 62: 

        } else if (reason = XP_ERROR_REQUEST_PERM_TIMEOUT || reason = XP_ERROR_NOT_PERMITTED || reason = XP_ERROR_NOT_FOUND) {
             llInstantMessage(agent, "Please accept the experience or bad things may happen!"); 
            } 

Might be something there...

 

Here is the final code so far it's working ;) Try it out or post your comments below if you have better ways. There might be a way to make a separate function for the switch and teleports. 

vector teleportme = <212,150,1000>;
string MyObjectName;
string textdefault = "Teleport to platform!";
//Begin code
string theerror;
integer error;
key agent;
integer type;

//this is for the function added to switch on or off globally
//this float is needed for the fuction contributed by Rolig Loon
float iTouched;

default
{
    state_entry()
    {
         iTouched = FALSE;
        MyObjectName = llGetObjectName();
        //llVolumeDetect(TRUE); Removed because testing timer instead of using volume detect
        llSetText(textdefault, <1.0, 1.0, 1.0>, 1.0);
    }
    collision_start(integer num)
    { 
       agent = llDetectedKey(0); type = llDetectedType(0);
       if (type == (AGENT | ACTIVE) ) // 1 + 2
        {
            llRequestExperiencePermissions(agent, "");
        }   
    } 
//Timer added by Rolig Loon https://community.secondlife.com/profile/796876-rolig-loon/
timer()
{
    llSetTimerEvent(0.0);
    iTouched = FALSE;
}
    experience_permissions(key agent) {
        
        //touch function added and contributed by Rolig Loon https://community.secondlife.com/profile/796876-rolig-loon/ with some tweaks
        if (iTouched = TRUE)
        {
       
            // Do your TP stuff
            llSetText(llKey2Name(agent) + " is using the teleporter please wait...", <1.0, 1.0, 1.0>, 1.0);
            llTeleportAgent(agent, "", teleportme, teleportme);
            llSetTimerEvent(2.0);   // Here's your substitute for a llSleep contributed by Rolig Loon 
        }
             llSetText(textdefault, <1.0, 1.0, 1.0>, 1.0);   
    }
    
    experience_permissions_denied(key agent, integer reason){
        string theerror = llGetExperienceErrorMessage((integer)reason);
        if(reason = XP_ERROR_THROTTLED) {
                 //touch function added and contributed by Rolig Loon https://community.secondlife.com/profile/796876-rolig-loon/ 
                 //with some tweaks
                if (iTouched = TRUE)
                {
                    
                     llSetTimerEvent(4.0);    // Here's your substitute for a llSleep contributed by Rolig Loon 
                  }
        } else if (reason = XP_ERROR_REQUEST_PERM_TIMEOUT || reason = XP_ERROR_NOT_PERMITTED || reason = XP_ERROR_NOT_FOUND) {
             llInstantMessage(agent, "Please accept the experience or bad things may happen!"); 
            } 
        if(!llAgentInExperience(agent)) {
         llRequestExperiencePermissions(agent, "");  
         //llRequestExperiencePermissions(llDetectedKey(0), "");
        }
       
    }
    
    touch_start(integer total_number)
    {
      iTouched = TRUE;
     agent = llDetectedKey(0);  type = llDetectedType(0);
                  if (type == (AGENT | ACTIVE) ) // 1 + 2
                   {
                     llRequestExperiencePermissions(agent, "");
                    } 

    }
     
}

 

Share this post


Link to post
Share on other sites

I didn't check the code in detail but in experience_permissions_denied you wrongly use "=" (assignment) instead of "==" (compare) in all if's.

Same in experience_permissions.

And you use llDetectedKey and that doesn't work here - you need to use agent instead.

Share this post


Link to post
Share on other sites

I have checked the code and simplified it and  tidied it up rather.   I've not tested it in-world but I think it looks right.  

It really might be better, in future, if people post code they're working on in the main script forum and only put the finished version here in the library.   I don't think the library is the place for works in progress.


integer iTouched;
vector vTeleportTarget = <212,150,1000>;
string strMyObjectName;
string strTextDefault = "Teleport to platform!";
//Begin code

key kAgent;
//integer iType;

//this is for the function added to switch on or off globally
//this float is needed for the fuction contributed by Rolig Loon


default
{
    state_entry()
    {
        iTouched = FALSE;
        strMyObjectName = llGetObjectName();
        //llVolumeDetect(TRUE); Removed because testing timer instead of using volume detect
        llSetText(strTextDefault, <1.0, 1.0, 1.0>, 1.0);
    }
    collision_start(integer num)
    {
        if(!iTouched){ //ignore it if I'm in use 
           
           if (llDetectedType(0) & AGENT)
            {
                kAgent = llDetectedKey(0);  
                llSetText(llGetDisplayName(kAgent) + " is using the teleporter please wait...", <1.0, 1.0, 1.0>, 1.0);
                llSetTimerEvent(10.0);//need to turn on the timer here in case the agent changes his mind and wanders off.  If this happens, the object eventually becomes touchable again.
                iTouched = TRUE;
                llRequestExperiencePermissions(kAgent, ""); //no need to test for llAgentInExperience -- if the agent is, then he'll be teleported and if he's not, the simulator will ask him to accept the experience.
             }
        }
    }
    //Timer added by Rolig Loon https://community.secondlife.com/profile/796876-rolig-loon/
    timer()
    {
        iTouched =FALSE;
        llSetText(strTextDefault, <1.0, 1.0, 1.0>, 1.0);
        
    }
    experience_permissions(key agent) {
        if(agent == kAgent){//should always be, but it can sometimes be an issue if people leave the region unexpectedly -- eg crash
               // Do your TP stuff
            llTeleportAgent(kAgent, "", vTeleportTarget, vTeleportTarget);
            llSetTimerEvent(2.0);   // Here's your substitute for a llSleep contributed by Rolig Loon

        }
        
    }


    touch_start(integer total_number)
    {
        if(!iTouched){ // no one can touch it again while it's trying to teleport you
           
           if (llDetectedType(0) & AGENT) //though how on earth you can touch things without being an agent is a bit of puzzle
            {
                kAgent = llDetectedKey(0);  
                llSetText(llGetDisplayName(kAgent) + " is using the teleporter please wait...", <1.0, 1.0, 1.0>, 1.0);
                llSetTimerEvent(10.0);//need to turn on the timer here in case the toucher changes his mind and wanders off.  If this happens, the object becomes touchable again.
                iTouched = TRUE;
                llRequestExperiencePermissions(kAgent, ""); //no need to test for llAgentInExperience -- if the agent is, then he'll be teleported and if he's not, the simulator will ask him to accept the experience.
             }
        }
    }

}

 

  • Like 2

Share this post


Link to post
Share on other sites
20 minutes ago, Innula Zenovka said:

It really might be better, in future, if people post code they're working on in the main script forum and only put the finished version here in the library.   I don't think the library is the place for works in progress.

Yes. B|

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×