Difference between revisions of "LlTeleportAgent"

From Second Life Wiki
Jump to navigation Jump to search
(the description of lookAt was wrong when a landmark is provided)
m
 
(13 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{LSL_Function
{{LSL_Function
|inject-2={{LSL Function/avatar|avatar|region=*}}{{LSL Function/inventory|landmark|type=landmark|uuid=false|empty=(for teleporting within the same region)}}{{Issues/BUG-4062}}{{Issues/SVC-7987}}
|inject-2={{LSL Function/avatar|agent|region=*}}{{LSL Function/inventory|landmark|type=landmark|uuid=false|empty=(for teleporting within the same region)}}{{Issues/BUG-4062}}{{Issues/SVC-7987}}
|inject-3={{LSL_Function/permission|PERMISSION_TELEPORT|grant={{LSLP|avatar}}}}
|inject-3={{LSL_Function/permission|PERMISSION_TELEPORT|grant={{LSLP|agent}}}}
|func=llTeleportAgent
|func=llTeleportAgent
|sort=TeleportAgent
|sort=TeleportAgent
|p1_type=key|p1_name=avatar|p1_desc= (the avatar to teleport, must be the [[llGetOwner|owner]])|p1_hover= (the avatar to teleport, must be the owner)
|p1_type=key|p1_name=agent|p1_desc= (the avatar to teleport, must be the [[llGetOwner|owner]])|p1_hover= (the avatar to teleport, must be the owner)
|p2_type=string|p2_name=landmark|p2_desc
|p2_type=string|p2_name=landmark|p2_desc
|p3_type=vector|p3_name=position|p3_desc=The position within the local region to teleport the avatar to if no landmark was provided.
|p3_type=vector|p3_name=position|p3_desc=The position within the local region to teleport the avatar to if no landmark was provided.
|p4_type=vector|p4_subtype=direction|p4_name=look_at|p4_desc=If landmark is provided, a ''direction'' to face (same as in [[llTeleportAgentGlobalCoords]]). If landmark is not provided, the position within the region that the avatar should be turned to face upon arrival.
|p4_type=vector|p4_name=look_at|p4_desc=The position within the region that the avatar should be turned to face upon arrival.
|func_desc=Requests a teleport of {{LSLP|avatar}} to a {{LSLP|landmark}} stored in the object's inventory. If no landmark is provided (an empty string), the avatar is teleported to the location {{LSLP|position}} in the current region. In either case, the avatar is turned to face the direction given by {{LSLP|look_at}}.
|func_desc=Teleports an {{LSLP|agent}} to a {{LSLP|landmark}} stored in the object's inventory.
 
If {{LSLP|landmark}} is an empty string, the avatar is teleported to the location {{LSLP|position}} in the current region.
 
If the destination is in the current region, the avatar will land facing {{LSLP|look_at}} as a position within that region. Otherwise, {{LSLP|look_at}} is treated as a unit direction.
|func_footnote
|func_footnote
|caveats=
|caveats=
* '''This function can only teleport the owner of the object''' (unless part of an [[:Category:Experience Tools|Experience]]).
* '''This function can only teleport the owner of the object''' (unless part of an [[:Category:Experience Tools|Experience]]).
* Teleports are throttled
* Teleports are throttled (no more than 10 teleports within 15 seconds)
* This function cannot be used in a script in an object attached using [[llAttachToAvatarTemp]].
* Does not work in scripts within attached temp objects {{LSLG|llAttachToAvatarTemp}}. Error Message is "Temporary attachments cannot request runtime permissions to teleport"
* Sitting avatars cannot be teleported using this function. You must [[llUnSit]] them first.
* Sitting avatars cannot be teleported using this function. You must [[llUnSit]] them first.
* This function does not override a parcel's teleport settings, i.e. if the parcel has a landing zone enabled the agent will be teleported there.
* This function does not override a parcel's teleport settings, i.e. if the parcel has a landing zone enabled the avatar will be teleported there.
* If the script is part of an experience that the avatar has granted permission, then this function may teleport them without being the owner and it will override parcel teleport routing. See the example below.
* If the script is part of an experience that the avatar has granted permission, then this function may teleport them without being the owner and it will override parcel teleport routing. See the example below.
* When {{LSLPT|look_at}} is treated as a direction, a valid input should be <code><llCos(angle), llSin(angle), 0.0></code>.
** In other words, it should be a '''unit vector''' corresponding to the avatar turning '''angle''' radians from north.
|examples=
|examples=
'''Without a landmark in the object's inventory'''
Basic example with a landmark called '''Destination''' in the object's inventory:
<source lang="lsl2">key  teleportee;
<syntaxhighlight lang="lsl2">
 
default
default
{
{
     state_entry()
     touch_start(integer num_detected)
     {
     {
         llSay(0, "Touch to teleport");
         llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
     }
     }


    touch_start(integer total_num)
    {
        teleportee = llDetectedKey(0);
        llRequestPermissions(teleportee, PERMISSION_TELEPORT);
    }
   
     run_time_permissions(integer perm)
     run_time_permissions(integer perm)
     {
     {
         if(PERMISSION_TELEPORT & perm)
         if (PERMISSION_TELEPORT & perm)
         {
         {
             llTeleportAgent(teleportee, "", <13.0, 38.0, 23.5>, <13.0, 12.0, 23.5>);
             llTeleportAgent(llGetPermissionsKey(), "Destination", ZERO_VECTOR, ZERO_VECTOR);
         }
         }
     }
     }
}
}
</source>
</syntaxhighlight>
'''With a landmark in the objects inventory'''
Basic example without a landmark in the object's inventory, while facing the avatar towards the center of the region:
<source lang="lsl2">
<syntaxhighlight lang="lsl2">
key  teleportee;
 
default
default
{
{
     state_entry()
     touch_start(integer num_detected)
     {
     {
         llSay(0, "Touch to teleport");
         llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
     }
     }


    touch_start(integer total_num)
    {
        teleportee = llDetectedKey(0);
        llRequestPermissions(teleportee, PERMISSION_TELEPORT);
    }
   
     run_time_permissions(integer perm)
     run_time_permissions(integer perm)
     {
     {
         if(PERMISSION_TELEPORT & perm)
         if (PERMISSION_TELEPORT & perm)
         {
         {
             llTeleportAgent(teleportee, "Experience Tools 1", <0.0, 0.0, 0.0>, <0.0, 0.0, 0.0>);
             vector region_pos = <100, 130, 40>;
            vector look_at = <128,128,40>;
            llTeleportAgent(llGetPermissionsKey(), "", region_pos, look_at);
         }
         }
     }
     }
}
}
</source>
</syntaxhighlight>
'''How to use this function in an Experience'''
'''How to use this function in an Experience'''
<source lang="lsl2">
<syntaxhighlight lang="lsl2">
// A SIMPLE SCRIPT that implements an Experience based teleport.
// A SIMPLE SCRIPT that implements an Experience based teleport.
// Compile with the "Use Experience" box cnecked and an experience key you own selected.
// Compile with the "Use Experience" box cnecked and an experience key you own selected.
Line 87: Line 80:
// See https://community.secondlife.com/t5/English-Knowledge-Base/Experiences-in-Second-Life/ta-p/2744686
// See https://community.secondlife.com/t5/English-Knowledge-Base/Experiences-in-Second-Life/ta-p/2744686
// to read what the Lindens think is an adequate explanation of all this.
// to read what the Lindens think is an adequate explanation of all this.


default
default
Line 95: Line 87:
         llRequestExperiencePermissions(llDetectedKey(0), "");
         llRequestExperiencePermissions(llDetectedKey(0), "");
     }
     }
      
 
     experience_permissions(key av)
    experience_permissions(key agent)
     {
        llTeleportAgent(agent, "Landmark", ZERO_VECTOR, ZERO_VECTOR);
     }
}
</syntaxhighlight>
 
Below is an example of properly handling the '''look_at''' value based on whether the destination is the current region or a different one. This ensures that the avatar will always be facing the same ''direction'' regardless of whether they're teleporting within the region or to another one.
 
The script keeps track of the landmark's destination coordinate in the '''state_entry''' and '''changed''' events, which is later used to calculate the total distance of the teleport.
<syntaxhighlight lang="lsl2">
string landmark;
vector destination;
 
default
{
    state_entry()
    {
        // Get data about the first landmark in object inventory when script starts.
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }
 
    changed(integer change)
    {
        if (!(change & (CHANGED_INVENTORY|CHANGED_REGION))) return;
 
        // Get data about the first landmark in object inventory when inventory changes.
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }
 
    dataserver(key query, string data)
    {
        // Save llRequestInventoryData response.
        destination = (vector)data;
    }
 
    touch_start(integer num_detected)
     {
     {
         llTeleportAgent(av, "Landmark", ZERO_VECTOR, ZERO_VECTOR);
        llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
    }
 
    run_time_permissions(integer perm)
    {
        if (!(PERMISSION_TELEPORT & perm)) return;
 
        float angle = 45 * DEG_TO_RAD;
 
        // When teleporting to another region, we need a direction vector.
        vector look_at = <llCos(angle), llSin(angle), 0>;
 
        float sim_size = llVecMag(<1,1,1>);
        float distance = llVecDist(<1,1,1>, destination / 256);
 
        if (distance < sim_size) {
            // When teleporting within the current region, we should use a position within the region instead.
            look_at = destination + look_at;
        }
 
         llTeleportAgent(llGetPermissionsKey(), landmark, ZERO_VECTOR, look_at);
     }
     }
}
}
</source>
</syntaxhighlight>
 
Another example, submitted by [[User:Jesse_Barnett|Jesse Barnett]], shows how to use a list of landmarks inside a HUD to allow teleporting, even inside a no-script area: [[Teleport HUD]].
|also_functions=
|also_functions=
{{LSL DefineRow||[[llTeleportAgentGlobalCoords]]|Teleports an agent to a global position.}}
{{LSL DefineRow||[[llTeleportAgentGlobalCoords]]|Teleports an agent to a global position.}}
|notes=
|notes=
|history = Date of Release  [[ Release_Notes/Second_Life_Server/12#12.07.24.262437 | 24/07/2012 ]]
|cat1=Teleport
|cat1=Teleport
|cat2
|cat2=Experience
|cat3
|cat3=Permissions/Experience
|history = Date of Release  [[ Release_Notes/Second_Life_Server/12#12.07.24.262437 | 24/07/2012 ]]
}}
}}
[[Category:Experience Tools]]

Latest revision as of 19:45, 27 January 2024

Summary

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

Teleports an agent to a landmark stored in the object's inventory.

If landmark is an empty string, the avatar is teleported to the location position in the current region.

If the destination is in the current region, the avatar will land facing look_at as a position within that region. Otherwise, look_at is treated as a unit direction.

• key agent avatar UUID that is in the same region (the avatar to teleport, must be the owner)
• string landmark a landmark in the inventory of the prim this script is in or an empty string (for teleporting within the same region)
• vector position The position within the local region to teleport the avatar to if no landmark was provided.
• vector look_at The position within the region that the avatar should be turned to face upon arrival.

To run this function the script must request the PERMISSION_TELEPORT permission with llRequestPermissions and it must be granted by agent.

Caveats

  • If landmark is not an empty string and...
    • landmark is missing from the prim's inventory or it is not a landmark then an error is shouted on DEBUG_CHANNEL.
Permissions
  • Once the PERMISSION_TELEPORT permission is granted there is no way to revoke it except from inside the script (for example, with a new llRequestPermissions call) or the script is reset or deleted.
  • This function can only teleport the owner of the object (unless part of an Experience).
  • Teleports are throttled (no more than 10 teleports within 15 seconds)
  • Does not work in scripts within attached temp objects llAttachToAvatarTemp. Error Message is "Temporary attachments cannot request runtime permissions to teleport"
  • Sitting avatars cannot be teleported using this function. You must llUnSit them first.
  • This function does not override a parcel's teleport settings, i.e. if the parcel has a landing zone enabled the avatar will be teleported there.
  • If the script is part of an experience that the avatar has granted permission, then this function may teleport them without being the owner and it will override parcel teleport routing. See the example below.
  • When look_at is treated as a direction, a valid input should be <llCos(angle), llSin(angle), 0.0>.
    • In other words, it should be a unit vector corresponding to the avatar turning angle radians from north.

Examples

Basic example with a landmark called Destination in the object's inventory:

default
{
    touch_start(integer num_detected)
    {
        llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
    }

    run_time_permissions(integer perm)
    {
        if (PERMISSION_TELEPORT & perm)
        {
            llTeleportAgent(llGetPermissionsKey(), "Destination", ZERO_VECTOR, ZERO_VECTOR);
        }
    }
}

Basic example without a landmark in the object's inventory, while facing the avatar towards the center of the region:

default
{
    touch_start(integer num_detected)
    {
        llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
    }

    run_time_permissions(integer perm)
    {
        if (PERMISSION_TELEPORT & perm)
        {
            vector region_pos = <100, 130, 40>;
            vector look_at = <128,128,40>;
            llTeleportAgent(llGetPermissionsKey(), "", region_pos, look_at);
        }
    }
}

How to use this function in an Experience

// A SIMPLE SCRIPT that implements an Experience based teleport.
// Compile with the "Use Experience" box cnecked and an experience key you own selected.
// The prim containing this script must contain a landmark named "Landmark" in its contents
//
// If the person touching this box has not previously accepted an invitation to your experience,
// that person will be offered that opportunity when this prim is touched, and if the invitations
// is accepted, will be immediately teleported to the target of the landmark.
//
// If the toucher has previously accepted an invitation, the person will be immediately teleported
// with no interruption.
//
// The script has no safety features, e.g., will simply fail if the prim contains no landmark.
//
// Thanks to Rolig Loon for her help in figuring out how to do this
// See https://community.secondlife.com/t5/English-Knowledge-Base/Experiences-in-Second-Life/ta-p/2744686
// to read what the Lindens think is an adequate explanation of all this.

default
{
    touch_start(integer n)
    {
        llRequestExperiencePermissions(llDetectedKey(0), "");
    }

    experience_permissions(key agent)
    {
        llTeleportAgent(agent, "Landmark", ZERO_VECTOR, ZERO_VECTOR);
    }
}

Below is an example of properly handling the look_at value based on whether the destination is the current region or a different one. This ensures that the avatar will always be facing the same direction regardless of whether they're teleporting within the region or to another one.

The script keeps track of the landmark's destination coordinate in the state_entry and changed events, which is later used to calculate the total distance of the teleport.

string landmark;
vector destination;

default
{
    state_entry()
    {
        // Get data about the first landmark in object inventory when script starts.
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

    changed(integer change)
    {
        if (!(change & (CHANGED_INVENTORY|CHANGED_REGION))) return;

        // Get data about the first landmark in object inventory when inventory changes.
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

    dataserver(key query, string data)
    {
        // Save llRequestInventoryData response.
        destination = (vector)data;
    }

    touch_start(integer num_detected)
    {
        llRequestPermissions(llGetOwner(), PERMISSION_TELEPORT);
    }

    run_time_permissions(integer perm)
    {
        if (!(PERMISSION_TELEPORT & perm)) return;

        float angle = 45 * DEG_TO_RAD;

        // When teleporting to another region, we need a direction vector.
        vector look_at = <llCos(angle), llSin(angle), 0>;

        float sim_size = llVecMag(<1,1,1>);
        float distance = llVecDist(<1,1,1>, destination / 256);

        if (distance < sim_size) {
            // When teleporting within the current region, we should use a position within the region instead.
            look_at = destination + look_at;
        }

        llTeleportAgent(llGetPermissionsKey(), landmark, ZERO_VECTOR, look_at);
    }
}
Another example, submitted by Jesse Barnett, shows how to use a list of landmarks inside a HUD to allow teleporting, even inside a no-script area: Teleport HUD.

See Also

Events

•  run_time_permissions Permission receiving event

Functions

•  llGetPermissions Get the permissions granted
•  llGetPermissionsKey Get the agent who granted permissions
•  llRequestPermissions Request permissions
•  llTeleportAgentGlobalCoords Teleports an agent to a global position.

Articles

•  Script permissions

Deep Notes

History

Date of Release 24/07/2012

Signature

function void llTeleportAgent( key agent, string landmark, vector position, vector look_at );