Jump to content

teleporter using object names instead of coordinate vectors


testgenord1
 Share

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

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

Recommended Posts

Hi!
I've got a script that uses the name of an object in order to teleport the avatar to that object,
instead of using its coordinates.
It uses llSensor in order to find the name of that particular object and then teleports the avatar to that object.
This is quite convenient, particularly when you have to rearrange the object to a different location.
The teleporter is initiated by touch_start.

Now, I would like to change the teleporter in a way that it is initiated by llListen instead of touch_start,
(e.g. on typing in "#1", the avatar is supposed to be teleported to the object named "#1" etc).

However, I can't combine the llListen with the llSensor used in the script.
Do you maybe have an idea of how to initiate the script using llListen?
Thank you very much in advance!

Here is the script:

// Target Sensor Teleporter v0.1 by djphil (CC-BY-NC-SA 4.0)

key user;

default
{
    state_entry()
    {
        llOwnerSay("Initialisation ...");
    }

    touch_start(integer number)
    {
        user = llDetectedKey(0);
        llSensor("#1", "", PASSIVE, 96.0, PI);
        llSetText("#1", <1.0, 1.0, 1.0>, 1.0);
    }

    sensor(integer number)
    {
        vector det_pos = llDetectedPos(0);
        rotation det_rot = llDetectedRot(0);
        //osTeleportObject(llGetKey(), det_pos, det_rot, OSTPOBJ_NONE);
        osTeleportAgent(user, det_pos, ZERO_VECTOR);
    }

    no_sensor()
    {
        llSensor("#1", "", PASSIVE, 96.0, PI);
        llSetText("#1", <1.0, 1.0, 1.0>, 1.0);
    }
}



 

Link to comment
Share on other sites

First, get rid of that script. It's not written for use in SL.  It uses commands designed for the OS Grid, and it is using the no_sensor event to drive a repeating sensor that never turns off again.  Then write yourself a new script that uses a listen event instead of touch_start and, if necessary, uses llSensorRepeat and has a timer to shut it off after a few cycles or when it has detected CHANGED_TELEPORT in a changed event.  Also, reconsider whether you really want your device to sense only PASSIVE objects (that is, non-moving objects with no active scripts).

  • Like 2
Link to comment
Share on other sites

Hi again!
Thank you very much for your help.
I still couldn't quite achieve it, so I ended up using a workaround,
which is, you sit on a vehicle, which in turn is moved to objects having particular names through your chat messages.
For each object name typed in, a different state in the script is initiated, which, unfortunately, is a bit clumsy.

It works, though, at least on OSGRid / Opensim.
I'm sorry it's a bit ugly, but I'm still a beginner.
In case anyone would like to comment, I would appreciate that.
Thanks again!

key user;

vector sit_position = <0.0, 0.0, 0.1>;
vector sit_rotation = <0.0, 0.0, 0.0>;

integer target_id;
vector target_pos;

default
{
    state_entry()
    {
       llSitTarget(sit_position, llEuler2Rot(sit_rotation * DEG_TO_RAD));
       llListen(PUBLIC_CHANNEL, "", NULL_KEY, "");
    }
    listen(integer channel, string name, key id, string message)
    {
        message = llStringTrim(message, STRING_TRIM);
         
        if(message == "1")
        {
         state a;
        }
         if(message == "2")
        {
         state b;
        }
        else
        {
            llResetScript();
        }   
    }
}

state a
{
    state_entry()
    { 
    llSetStatus(STATUS_PHYSICS, TRUE);
    llSensor ("1","",PASSIVE,96.0,PI);
    }
    sensor(integer num)
    {  
    vector iTarget = llDetectedPos(0);
    vector offset =<-3,0,0>;  
    iTarget+=offset;
    target_id = llTarget(iTarget, 1.0);
    llMoveToTarget(iTarget,0.5);
    }
    at_target(integer tnum, vector targetpos, vector ourpos)
    {
        if (tnum == target_id)
        {
            llSetStatus(STATUS_PHYSICS, FALSE);
            key user = llAvatarOnSitTarget();
            if(user)
            {
            llSleep(1.0);
            llUnSit(user);
            llResetScript();
            }
        }
    }
}
  
state b
{
    state_entry()
    { 
    llSetStatus(STATUS_PHYSICS, TRUE);
    llSensor ("2","",PASSIVE,96.0,PI);
    }
    sensor(integer num)
    {  
    vector iTarget = llDetectedPos(0);
    vector offset =<-3,0,0>;  
    iTarget+=offset;
    target_id = llTarget(iTarget, 1.0);
    llMoveToTarget(iTarget,0.5);
    }
    at_target(integer tnum, vector targetpos, vector ourpos)
    {
        if (tnum == target_id)
        {
            llSetStatus(STATUS_PHYSICS, FALSE);
            key user = llAvatarOnSitTarget();
            if(user)
            {
            llSleep(1.0);
            llUnSit(user);
            llResetScript();
            }
        }
   }
}

 

Edited by testgenord1
Link to comment
Share on other sites

3 hours ago, testgenord1 said:

I'm sorry it's a bit ugly, but I'm still a beginner.
In case anyone would like to comment, I would appreciate that.

You can actually merge all of those states into a single state fairly easily, like so:

key user;

vector sit_position = <0.0, 0.0, 0.1>;
vector sit_rotation = <0.0, 0.0, 0.0>;

integer target_id;
vector target_pos;

default
{
    state_entry()
    {
        llSitTarget(sit_position, llEuler2Rot(sit_rotation * DEG_TO_RAD));
        llListen(PUBLIC_CHANNEL, "", NULL_KEY, "");
    }
    listen(integer channel, string name, key id, string message)
    {
        message = llStringTrim(message, STRING_TRIM);

        if(message == "1")
        {
            // state a;
            llSetStatus(STATUS_PHYSICS, TRUE);
            llSensor ("1","",PASSIVE,96.0,PI);
        }
        if(message == "2")
        {
            // state b;
            llSetStatus(STATUS_PHYSICS, TRUE);
            llSensor ("2","",PASSIVE,96.0,PI);
        }
        // This part is not necessary. The script will not get stuck.
        // else
        // {
        //     llResetScript();
        // }
    }

    sensor(integer num)
    {
        vector iTarget = llDetectedPos(0);
        vector offset = <-3,0,0>;
        iTarget += offset;
        target_id = llTarget(iTarget, 1.0);
        llMoveToTarget(iTarget,0.5);
    }

    at_target(integer tnum, vector targetpos, vector ourpos)
    {
        if (tnum == target_id)
        {
            llSetStatus(STATUS_PHYSICS, FALSE);
            key user = llAvatarOnSitTarget();
            if(user)
            {
                llSleep(1.0);
                llUnSit(user);
                // This is also not necessary for the script to work properly.
                // llResetScript();
            }
        }
    }
}

One thing that seems necessary to point out is that when the script gets to the "end" where there's no more code to execute, the script will just exit that event and wait until a new event is triggered (meaning it will restart from the top of that event again). You don't need to restart the whole script at the end of everything.

And just to clarify, "events" are those things like state_entry, listen, sensor, at_target, etc. The code in those events have to be triggered somehow, like the listen event is triggered every time a chat message is sent near the script, on a channel it's already listening on.

Edited by Wulfie Reanimator
  • Like 3
Link to comment
Share on other sites

That will work.  You've probably noticed, of course, that it's not a teleporter.  You've created a vehicle-like object to carry you to a named spot in the region (or at least any named spot within 96 meters).  If you're willing to sit on an object to go from one place to another, there are many ways to write variations on a standard sit-teleport script, too.  Your options increase if you are willing to put a simple script in the target objects so that you can follow a scheme like this:

1. You sit on Object A, thus triggering Object A's script

2. Object A uses llRegionSay to ask "Object B, are you out there?"

3. Object  B replies, "Here I am!".

4. Object A uses Object B's UUID and llGetObjectDetails ( OBJECT_POS) to see exactly where Object B is, and then

5. Uses llSetRegionPos to move to that position and then

6. Unseats you and either returns to where it started or dies.

Edited by Rolig Loon
typos, of course
  • Like 1
Link to comment
Share on other sites

Thank you very much for your support!
@Wulfie Reanimator: The script works nicely, thanks again.
- The trick about integrating the sensor event in the listen event seems to be to put the

sensor(integer num)

completely outside of the

listen(integer channel, string name, key id, string message)

brackets. Is that right?

- Thanks to your help I finally also was able to add a typecast to the script so that I can leave out the specific names of the target objects.
Here is the script:

rotation startrotation;
key user;

vector sit_position = <1.2, 0.0, 0.4>;
vector sit_rotation = <0.0, 0.0, 0.0>;

integer target_id;
vector target_pos;

default
{
    state_entry()
    {
        llSetStatus(STATUS_PHANTOM, TRUE);
        rotation startrotation = llGetRot();
        llSitTarget(sit_position, llEuler2Rot(sit_rotation * DEG_TO_RAD));
        llForceMouselook(TRUE);
     }
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            key av = llAvatarOnSitTarget();
            if (av) //evaluated as true if not NULL_KEY or invalid
            {
                llListen(PUBLIC_CHANNEL, "", NULL_KEY, "");
            }
        }
    }
    listen(integer channel, string name, key id, string message)
    {
        message = llStringTrim(message, STRING_TRIM);
        if(message)
        {
            llSetStatus(STATUS_PHYSICS, TRUE);
            llSensor ("hypertext mobbing "+message,"",PASSIVE | ACTIVE,96.0,PI);
        }
    }
    sensor(integer num)
    {
        vector iTarget = llDetectedPos(0);
        vector offset = <-4,-6,-2.5>;
        iTarget += offset;
        target_id = llTarget(iTarget, 1.0);
        llMoveToTarget(iTarget,0.5);
    }
    at_target(integer tnum, vector targetpos, vector ourpos)
    {
        if (tnum == target_id)
        {
            llSetStatus(STATUS_PHYSICS, FALSE);
            llSetRot (startrotation);  
            key user = llAvatarOnSitTarget();
            if(user)
            {
                llSleep(1.0);
                //llForceMouselook(FALSE);
                llUnSit(user);
                llResetScript();
            }
        }
    }
}

- Thanks for the idea about saving llResetScript.
The last llResetScript still seems to be necessary to prevent you from getting "unsit", when trying to sit on the vehicle again.
I also added a rotation correction in case the vehicle is accidentally rotated from hitting another object while moving.

@Rolig Loon: Thanks for the additional idea about the llGetObjectDetails option. It works nicely.
I had to split the vehicle script into two, though, but I guess that's fine.
I'm posting it for other users potentially interested in this:

vehicle script 1:

//https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/
//the sit-starter:

default
{
     state_entry()
     {
          llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
     }
     changed(integer change)
     {
        if (change & CHANGED_LINK)
        { 
            key av = llAvatarOnSitTarget();
            if (av)
            {
                llRegionSay(-10001,"where?");
            }
        }
    }
}

vehicle script 2:

//https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/
//the mover script:

default
{
    state_entry()
    {
        llListen(-10001,"", NULL_KEY,"");
    }
            listen(integer channel, string name, key id, string message)
            {
                if(message == "here.")
                {
                    list details = llGetObjectDetails(id, ([OBJECT_NAME, OBJECT_DESC,
                            OBJECT_POS, OBJECT_ROT, OBJECT_VELOCITY,
                            OBJECT_OWNER, OBJECT_GROUP, OBJECT_CREATOR]));
                            
                            vector position = llList2Vector(details,2);
                            
                            llSetRegionPos(position+<-1,0,0>);
                }
            }   
}

destination script:

//https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/
//destination script:

default
{
    state_entry()
    {
        llListen(-10001,"",NULL_KEY,"");
    }
    listen(integer channel, string name, key id, string message)
        {
            if(message == "where?")
            {
                llRegionSay(-10001, "here.");
            }
        }
}

Thanks again.

Edited by testgenord1
added changed event so only sitting avatar can start script.
Link to comment
Share on other sites

2 hours ago, testgenord1 said:

- The trick about integrating the sensor event in the listen event seems to be to put the completely outside of the brackets. Is that right?

Yes, all events must be entirely separate of each other. An event cannot contain an event. (But you can cause some events to trigger from another event, as you do with llSensor inside the listen event.)

Edited by Wulfie Reanimator
  • Like 2
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1718 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...