Jump to content

Teleport other avatars with HUD


Patrick Playfair
 Share

You are about to reply to a thread that has been inactive for 2520 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I have a HUD that can auto-attach thing to other avatars using experience, play sounds, TP the owner around the sim, etc. I modified it to use dialogs to choose a victim using llGettAgentList, and then to choose a teleport destination (destination menu auto-populates by reading landmarks in inventory).  It would then request experience permissions and TP the victim to any of the landmarks.  This all worked great, until I WORE the HUD.  Turns out that llRequestPermissions will not work with a HUD.  It generates the error "Attachment asking non-owner for experience permissions".  It doesn't do this as an object, only as a HUD, so I need to re-think this.  First of all, does anyone know a work-around for this.  I am considering using RLV to teleport the victim instead of experience permissions, but the RLV tpto: command uses coordinates as opposed to using landmarks.  I know that the Witchy Remote HUD is capable of getting the coordinates from inventory landmarks, so I know it can be done.  Anyone know of how I might accomplish this?

 

Link to comment
Share on other sites

If you want to request experience permissions, then you need to use llRequestExperiencePermissions, so that might be your problem right there.

If doesn't fix it, then we need to see your script.  I can assure you, though, that you can certainly rez a HUD from a rezzer, attach it to someone other than the owner of the rezzer and then have it request experience permissions and teleport the wearer somewhere.  I've made several HUDs that do exactly that.

ETA   Alternatively, once you've attached it, you can do an ordinary llRequestPermissions() call and teleport the owner in the run_time_permissions() event.  

It sounds to me as if you've defined kOwner somewhere in your script but aren't updating it when the HUD attaches to the avatar, with the result that the HUD is trying to teleport you, rather than the new owner.   But I'd need to see the script to be sure.

Edited by Innula Zenovka
Link to comment
Share on other sites

3 hours ago, Patrick Playfair said:

I am considering using RLV to teleport the victim instead of experience permissions, but the RLV tpto: command uses coordinates as opposed to using landmarks.  I know that the Witchy Remote HUD is capable of getting the coordinates from inventory landmarks, so I know it can be done.  Anyone know of how I might accomplish this?

Sorry, I forgot to address this.  I don't think you need to use RLV for your particular application, but it's useful to know how to extract the name of the target region of a landmark, so here's an old example of how I do it.   This example constructs a slurl but you should be able to construct the appropriate RLV command using it, referring to Marine's example in the RLV API in the wiki if necessary.

Sorry it's a bit convoluted.   It can probably be streamlined, but I'm too tired to work it out.

key LMid;
key simID;

key http_region_request;
vector global_pos;
vector target_pos;
string target;
default {
  state_entry() {

  }
  touch_start(integer n) {

    LMid = llRequestInventoryData(llGetInventoryName(INVENTORY_LANDMARK, 0));//get the landmark's target as an offset from <0,0,0> on the present region
  }
  dataserver(key requestID, string data) {
    llOwnerSay(data);
    string my_x;
    string my_y;
    string my_z;
    if (LMid==requestID){

      list tokens = llParseString2List (data, ["<", ",", ">"], []);//break the vector down into its x, y and z coordinates
      global_pos.x = llList2Float (tokens, 0);
      global_pos.y = llList2Float (tokens, 1);
      global_pos.z = llList2Float (tokens, 2);
      global_pos +=llGetRegionCorner(); //add the global coordinates of the region I'm on, to give the target region's global coordinates
      integer x = (integer) ( global_pos.x / 256.);
      integer y = (integer) ( global_pos.y / 256.);

      llOwnerSay( (string) global_pos + " x=" + (string) x + " y=" + (string) y);
      http_region_request = llHTTPRequest( "https://cap.secondlife.com/cap/0/b713fe80-283b-4585-af4d-a3b7d9a32492?var=x&grid_x=" + (string) x + "&grid_y=" + (string) y, [ HTTP_VERIFY_CERT, FALSE ], "");
      //ask SL for the name of the target region
    }

    else if (simID == requestID){
      llOwnerSay(data);
      target_pos = (vector)data;
      llOwnerSay((string)(global_pos-target_pos));
      target_pos = (global_pos-target_pos);//now subtract the region's global coordinates from the global_pos we originally calculated using the landmark, to get the target position on the region
      my_x =(string)target_pos.x;
      my_x = llGetSubString(my_x,0,(llSubStringIndex(my_x,".")-1));
      my_y =(string)target_pos.y;
      my_y = llGetSubString(my_y,0,(llSubStringIndex(my_y,".")-1));
      my_z =(string)target_pos.z;
      my_z = llGetSubString(my_z,0,(llSubStringIndex(my_z,".")-1));

      target_pos.y = (integer)target_pos.y;
      target_pos.z= (integer)target_pos.z;
      llOwnerSay("Click here: http://slurl.com/secondlife/"+target+"/"+my_x+"/"+my_y+"/"+my_z);

    }
  }

  http_response( key request_id, integer status, list metadata, string body)
  {
    if ( request_id == http_region_request)//reply giving name of target region
    {
      llOwnerSay( "body=>" + body + "<");
      integer start = llSubStringIndex( body, "var x='");
      if ( start >= 0)//extract the region's name
      {
        integer end = llSubStringIndex( llGetSubString( body, start + 7, -1), "';");
        if ( end >= 0)
        {
          llOwnerSay( llGetSubString( body, start + 7, start + 6 + end));
          target = llGetSubString( body, start + 7, start + 6 + end);
          simID = llRequestSimulatorData(target, DATA_SIM_POS);
        }
      }
    }


  }

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

 

Link to comment
Share on other sites

Maybe I am misreading the question, but it sounds like you are not trying to make the HUD teleport its owner at all. You want it to teleport another person chosen from a menu of detected avatars. If so, you are trying something like a god mode TP, which you can't do unless you are a Linden. You'll need to attach something to the person or have her touch, sit on, or collide with it. I can think of a few ways to do that (rez a temporary portal next to the person, for example, or rez something that force attaches) but nothing that does it simply by sending a TP command. But, as I say, I may be misreading the question. 

Link to comment
Share on other sites

49 minutes ago, Rolig Loon said:

You'll need to attach something to the person or have her touch, sit on, or collide with it.

The OP seems to be using experience perms.   Assuming the experience can run on the parcel, why can't the HUD detect nearby avatars, present the wearer with a menu, and then call llRequestExperiencePermissions(kSelectedAvatar,"") in the listen event?   

Edited by Innula Zenovka
Link to comment
Share on other sites

7 hours ago, Innula Zenovka said:

Sorry, I forgot to address this.  I don't think you need to use RLV for your particular application, but it's useful to know how to extract the name of the target region of a landmark, so here's an old example of how I do it.   This example constructs a slurl but you should be able to construct the appropriate RLV command using it, referring to Marine's example in the RLV API in the wiki if necessary.

Sorry it's a bit convoluted.   It can probably be streamlined, but I'm too tired to work it out.

 

 

1 hour ago, Rolig Loon said:

Maybe I am misreading the question, but it sounds like you are not trying to make the HUD teleport its owner at all. You want it to teleport another person chosen from a menu of detected avatars. If so, you are trying something like a god mode TP, which you can't do unless you are a Linden. You'll need to attach something to the person or have her touch, sit on, or collide with it. I can think of a few ways to do that (rez a temporary portal next to the person, for example, or rez something that force attaches) but nothing that does it simply by sending a TP command. But, as I say, I may be misreading the question. 

 

14 minutes ago, Innula Zenovka said:

The OP seems to be using experience perms.   Assuming the experience can run on the parcel, why can't the HUD detect nearby avatars, present the wearer with a menu, and then call llRequestExperiencePermissions(kSelectedAvatar,"") in the listen event?   

I am u sing experience permissions, and I do want to wear the HUD myself, and TP others.  If I place it on the ground, I can TP anyone, anywhere in the sim, TO anywhere in the sim.  It is only when I wear it as a HUD that it doesn't work and generates that error. Here is the script that does the teleporting.

list       gListFullNames;            // List of inventory landmarks
list       gListBriefNames;           // List of abbreviated landmark names for dialog buttons
integer    gPage;                     // Current dialog page number (counting from zero)
integer    gMaxPage;                  // Highest page number (counting from zero)
integer    gChan;                     // Channel used for dialog communications.
key        gUser;                     // Menu User
key        victim;                    // Avatar to Perform command on
string     name2;                     // Destination

DestinationMenu(key user)
{
    integer TotalChoices = (gListBriefNames != [] );        // get length of landmark list
 
    // set up scrolling buttons if needed
    list buttons = [ "<<", "EXIT ", ">>" ];
 
    integer ChoicesPerPage = 9;
    if (TotalChoices < 13)
    {
        buttons = [];
        ChoicesPerPage = 12;
    }
    // Compute number of menu pages that will be available
    gMaxPage = (TotalChoices - 1) / ChoicesPerPage;
    // Build a dialog menu for current page for given user
    integer start = ChoicesPerPage * gPage;       // starting offset into action list for current page
    // 'start + ChoicesPerPage -1' might point beyond the end of the list -
    // - but LSL stops at the list end, without throwing a wobbly
    buttons += llList2List(gListBriefNames, start, start + ChoicesPerPage - 1);
    llDialog(user, "\nPage " + (string) (gPage+1) + " of " + (string) (gMaxPage + 1) + "\n\nChoose a Destination", buttons, gChan);
    llSetTimerEvent(30);              // If no response in time, return to 'ready' state
}
 
default
{

    link_message(integer sender,integer num,string msg,key id)   
    {
        if (num == 2)
        {
            victim = id;
            // Compute a negative communications channel based on prim UUID
            integer gChan = (integer)(llFrand(99999.0) * -1);
            gUser = llGetOwner();
            integer count = llGetInventoryNumber(INVENTORY_LANDMARK);
            string name;
            while (count--)
            {
                name = llGetInventoryName(INVENTORY_LANDMARK, count);
                gListFullNames += name;
                gListBriefNames += llGetSubString(name, 0, 23);
            }
        }
        else
        {
        llResetScript();
        }
 
        state busy;
        // Changing state sets the application to a busy condition while one user is selecting from the dialogs
        // In the event of multiple 'simultaneous' touches, only one user will get a dialog
    }
    
}
 
state busy
{
    state_entry()
    {
        llListen(gChan, "", gUser, "");                // This listener will be used throughout this state
        gPage = 0;
        DestinationMenu(gUser);
    }
    listen (integer chan, string name, key id, string msg)
    {
        integer index;
        if (msg == "<<" || msg == ">>")                   // Page change ...
        {
            if (msg == "<<")        --gPage;              // Page back
            if (msg == ">>")        ++gPage;              // Page forward
            if (gPage < 0)          gPage = gMaxPage;     // cycle around pages
            if (gPage > gMaxPage)   gPage = 0;
            DestinationMenu(id);
            return;
        }
        if (msg != " ")                                  // no action on blank menu button
        {
            // User has selected a landmark from the menu
            llSetTimerEvent(0);
            index = llListFindList(gListBriefNames, [msg]);
            name2 = llList2String(gListFullNames, index);
            llRegionSayTo(gUser,0, "Teleporting " + (string)victim + " to " + name2);
            llRequestExperiencePermissions(victim,"");
        }
        else
        {
            llSetTimerEvent(0);
            llResetScript();
        }
    }
    experience_permissions(key Av)
    {
        llTeleportAgent(Av, name2,ZERO_VECTOR, ZERO_VECTOR);
        llResetScript();
    }
    experience_permissions_denied(key Av, integer reason)
    {
        llRegionSay(-11678,"Experience permissions failed for " + llKey2Name(Av) + ". Avatar cannot be teleported!");
        llResetScript();
    }
    
    timer()
    {
        llRegionSayTo(gUser, 0, "Too slow, menu cancelled");
        llResetScript();
    }
}

 

Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

Maybe I am misreading the question, but it sounds like you are not trying to make the HUD teleport its owner at all. You want it to teleport another person chosen from a menu of detected avatars. If so, you are trying something like a god mode TP, which you can't do unless you are a Linden. You'll need to attach something to the person or have her touch, sit on, or collide with it. I can think of a few ways to do that (rez a temporary portal next to the person, for example, or rez something that force attaches) but nothing that does it simply by sending a TP command. But, as I say, I may be misreading the question. 

Rezzing a portal or attaching a device that requests Experience Permissions and TP's them is a good idea, assuming I can get their position and do so even if they are way across t he sim.  Will give that a try.

Link to comment
Share on other sites

That looks as if it should work,  which suggests to me the problem is with the other script that sends this one a link message containing the target avatar's uuid.   Put in an llOwnerSay in the link_message event to check on llGetUsername(id) to be sure, but I can't see anything wrong with this script.

Can we see the other script, please?

Link to comment
Share on other sites

2 hours ago, Innula Zenovka said:

That looks as if it should work,  which suggests to me the problem is with the other script that sends this one a link message containing the target avatar's uuid.   Put in an llOwnerSay in the link_message event to check on llGetUsername(id) to be sure, but I can't see anything wrong with this script.

Can we see the other script, please?

The problem with the original is that when you are Requesting Experience permission's from a HUD, you can only request your own.  I ended up resolving it.  I rez an attachment, whichin turn TP's them.  This will not work with any agent in the sim as I had intended originally, but it will work with any agent close enough to attach an object to. 

The HUD has a dialog with several options, one is to Teleport.  If the user chooses Teleport, another dialog prompts them to choose an Avatar, after they choose n Avatar, they are prompted to choose a Destination via this script, which will rez an object which attaches to the victim.  It also passes the destination to the object.

 

// Multi-Page Landmark Selector 
// Omei Qunhua  April 2014
// Modified by Patrick Playfair
 
list       gListFullNames;            // List of inventory landmarks
list       gListBriefNames;           // List of abbreviated landmark names for dialog buttons
list       details;
integer    gPage;                     // Current dialog page number (counting from zero)
integer    gMaxPage;                  // Highest page number (counting from zero)
integer    gChan;                     // Channel used for dialog communications.
key        gUser;                     // Menu User
key        victim;                    // Avatar to Perform command on
vector     pos;
string     destination;                     // Destination


DestinationMenu(key user)
{
    integer TotalChoices = (gListBriefNames != [] );        // get length of landmark list
 
    // set up scrolling buttons if needed
    list buttons = [ "<<", "EXIT ", ">>" ];
 
    integer ChoicesPerPage = 9;
    if (TotalChoices < 13)
    {
        buttons = [];
        ChoicesPerPage = 12;
    }
    // Compute number of menu pages that will be available
    gMaxPage = (TotalChoices - 1) / ChoicesPerPage;
    // Build a dialog menu for current page for given user
    integer start = ChoicesPerPage * gPage;       // starting offset into action list for current page
    // 'start + ChoicesPerPage -1' might point beyond the end of the list -
    // - but LSL stops at the list end, without throwing a wobbly
    buttons += llList2List(gListBriefNames, start, start + ChoicesPerPage - 1);
    llDialog(user, "\nPage " + (string) (gPage+1) + " of " + (string) (gMaxPage + 1) + "\n\nChoose a Destination", buttons, gChan);
    llSetTimerEvent(30);              // If no response in time, return to 'ready' state
}
 
default
{

    link_message(integer sender,integer num,string msg,key id)   
    {
        if (num == 2)
        {
            victim = id;
            // Compute a negative communications channel based on prim UUID
            integer gChan = (integer)(llFrand(99999.0) * -1);
            gUser = llGetOwner();
            integer count = llGetInventoryNumber(INVENTORY_LANDMARK);
            string name;
            while (count--)
            {
                name = llGetInventoryName(INVENTORY_LANDMARK, count);
                gListFullNames += name;
                gListBriefNames += llGetSubString(name, 0, 23);
            }
        }
        else
        {
        llResetScript();
        }
 
        state busy;
        // Changing state sets the application to a busy condition while one user is selecting from the dialogs
        // In the event of multiple 'simultaneous' touches, only one user will get a dialog
    }
    
}
 
state busy
{
    state_entry()
    {
        llListen(gChan, "", gUser, "");                // This listener will be used throughout this state
        gPage = 0;
        DestinationMenu(gUser);
    }
    listen (integer chan, string name, key id, string msg)
    {
        integer index;
        if (msg == "<<" || msg == ">>")                   // Page change ...
        {
            if (msg == "<<")        --gPage;              // Page back
            if (msg == ">>")        ++gPage;              // Page forward
            if (gPage < 0)          gPage = gMaxPage;     // cycle around pages
            if (gPage > gMaxPage)   gPage = 0;
            DestinationMenu(id);
            return;
        }
        if (msg != " ")                                  // no action on blank menu button
        {
            // User has selected a landmark from the menu
            llSetTimerEvent(0);
            index = llListFindList(gListBriefNames, [msg]);
            destination = llList2String(gListFullNames, index);
            integer channel = llRound(llFrand(-1000));
            key give_to = victim;
            llRezObject("Alien Zapper!", llGetPos(), ZERO_VECTOR, ZERO_ROTATION, channel);
            llRegionSay(channel, "ATTACH|" + (string)give_to +"|" + destination);
            llResetScript();
        }
        else
        {
            llResetScript();
        }
    }

    timer()
    {
        llRegionSayTo(gUser, 0, "Too slow, menu cancelled");
        llResetScript();
    }
}

 

This script is in the object, which auto-attaches to the victim. After it attaches, it TP's the victim to the destination, then detaches.  Just for fun, when it attaches, it attaches as a big fat alien head to the center of their HUD, then disappears.

 

integer listener;
integer msg_channel;
key victim;
string destination;
 

default
{
    on_rez(integer start_parameter)
    {   // Start listening for a message from rezzer
        msg_channel = start_parameter;
        listener = llListen(start_parameter, "", NULL_KEY, "");
    }
 
    listen(integer channel, string name, key id, string text)
    {   // Listen for the message from the rezzer with the target agent key
        if (channel == msg_channel)
        {   // Ask for the experience permission
            list msg = llParseString2List(text, ["|"], []);
            destination = llList2String(msg, 2);           
            llRequestExperiencePermissions((key)llList2String(msg, 1), "");
            llListenRemove(listener);
            llSetTimerEvent(60.0);
        }
    }
 
    experience_permissions(key target_id)
    {   // Permissions granted, so attach to the AV
        victim = target_id;
        llAttachToAvatarTemp(ATTACH_HUD_CENTER_1);
        llSetTimerEvent(0.0);
        if (llGetAttached() == 0)
        {   // Attaching failed
            llDie();
        }
    }
 
    experience_permissions_denied( key agent_id, integer reason )
    {   // Permissions denied, so go away
        llRegionSay(-11678,"Experience permissions denied for " + llKey2Name(agent_id));
        llDie();
    }
 
    attach( key id )
    {   // Attached or detached from the avatar
        if (id)
        {
            llSetTimerEvent(0.0);
            // From this point, the object can start doing whatever it needs to do.
            state running;
        }
        else
        {
            llDie();
        }
    }
 
    timer()
    {   // Use a timer to catch no permissions response
        llRegionSay(-11678, "Permissions timer expired");
        llDie();
    }
}
 
// This state starts when permissions are granted and the object is properly attached
state running
{
    state_entry()
    {
        llTeleportAgent(victim,destination, ZERO_VECTOR, ZERO_VECTOR);
        llSleep(2);
        llDetachFromAvatar();
    }
    
 
    attach(key id)
    {
        if (id == NULL_KEY)
        {   // if the object ever un-attaches, make sure it deletes itself
            llDie();
        }
    }
}

 

Link to comment
Share on other sites

This is interesting. To my best reading of the wiki page for llTeleportAgent(), it's not documented that attached scripts are unable to hold experience permissions for other, non-owner agents, but that seems to be the conclusion here, so it probably would be good if somebody who has wiki-editing permission (I don't) could update the documentation accordingly.

An alternative approach would be to have the teleporting happen from an unattached prim, rezzed somewhere on an Experience-enabled part of the region, and have your HUD send it llRegionSayTo() messages, telling it whom and whither to teleport, and have it get the Experience permissions from that victim, avoiding the need to attach anything to them. (Thinking ahead, it may be necessary to maintain a little queue of victims and destinations, in case multiple permission requests and responses get interleaved.)

  • Like 1
Link to comment
Share on other sites

3 hours ago, Innula Zenovka said:

I've just tested it and Patrick is right -- you can't teleport people using something attached to you, as opposed to them   I had misunderstood the first post, and thought the hud was to teleport the wearer.

 

I run an "Alien Abduction" based theme with a lot of traps, and an alien staff.  The Staff can now use the HUD to TP any nearby avatars to anywhere they want them.  From the HUD they can also play "Alien" sound clips, or impregnate the victims with a chestburster, which chats a storyline, knocks them out, and explodes into dozens of baby aliens.  Working good so far, now I need to add of Force Sit to the HUD.

  • Like 1
Link to comment
Share on other sites

http://wiki.secondlife.com/wiki/LlSitOnLink sadly won't work from an HUD as the function is host centric. You will have to execute it from the rezzed object you want targets to be forced sat upon.

I lobbied to get it to allow remote sitting on anything the target owns, but it was denied. It seemed the author wanted the feature to be as simple as possible which is a shame.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2520 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...