Jump to content

LookAt for llTeleportAgent and llTeleportAgentGlobalCoords


Wulfie Reanimator
 Share

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

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

Recommended Posts

I've just updated the wiki pages for these functions since their descriptions were fairly misleading, and the examples didn't really cover enough:

https://wiki.secondlife.com/wiki/LlTeleportAgent
https://wiki.secondlife.com/wiki/LlTeleportAgentGlobalCoords

Writing those examples was a fairly upsetting process, since the LookAt "direction" behaves completely differently based on the destination, and there's no neat way to find out whether a teleport would exit the current region.

For llTeleportAgentGlobalCoords: You have to keep track of your current region's global coordinate, so you can compare it with the global coordinates of your destination.

vector current_region;

default
{
    state_entry()
    {
        llRequestSimulatorData(llGetRegionName(), DATA_SIM_POS);
    }

    changed(integer change)
    {
        if (!(change & CHANGED_REGION)) return;
        llRequestSimulatorData(llGetRegionName(), DATA_SIM_POS);
    }

    dataserver(key query, string data)
    {
        current_region = (vector)data;
    }

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

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

        vector global_coord = <232704, 291072, 0>;
        vector region_pos = <122, 122, 40>;

        float angle = 45 * DEG_TO_RAD;
        vector look_at = <llCos(angle), llSin(angle), 0>;

        if (current_region == global_coord) {
            look_at = region_pos + look_at;
        }

        llTeleportAgentGlobalCoords(llGetOwner(), global_coord, region_pos, look_at);
    }
}

 

For llTeleportAgent: You have to keep track of the landmark's global coordinate, and then calculate the total distance to the destination. This one is especially tricky to implement because the landmark's coordinate can either be a region-local coordinate like <100, 130, 40>, or a global coordinate + region-local offset like <-131704.6, -24381.2, 22.48>, depending on whether you're in the same sim or not.

string landmark;
vector destination;

default
{
    state_entry()
    {
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

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

        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

    dataserver(key query, string data)
    {
        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;
        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) {
            look_at = destination + look_at;
        }

        llTeleportAgent(llGetOwner(), landmark, ZERO_VECTOR, look_at);
    }
}

 

These examples cover a semi-common corner-case where the destination is something you will teleport to from multiple regions (including the destination itself). Without this kind of handling, you might arrive at the destination with the wrong orientation.

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

  • 1 month later...
On 11/12/2022 at 12:01 AM, Wulfie Reanimator said:

I've just updated the wiki pages for these functions since their descriptions were fairly misleading, and the examples didn't really cover enough:

https://wiki.secondlife.com/wiki/LlTeleportAgent
https://wiki.secondlife.com/wiki/LlTeleportAgentGlobalCoords

Writing those examples was a fairly upsetting process, since the LookAt "direction" behaves completely differently based on the destination, and there's no neat way to find out whether a teleport would exit the current region.

For llTeleportAgentGlobalCoords: You have to keep track of your current region's global coordinate, so you can compare it with the global coordinates of your destination.

vector current_region;

default
{
    state_entry()
    {
        llRequestSimulatorData(llGetRegionName(), DATA_SIM_POS);
    }

    changed(integer change)
    {
        if (!(change & CHANGED_REGION)) return;
        llRequestSimulatorData(llGetRegionName(), DATA_SIM_POS);
    }

    dataserver(key query, string data)
    {
        current_region = (vector)data;
    }

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

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

        vector global_coord = <232704, 291072, 0>;
        vector region_pos = <122, 122, 40>;

        float angle = 45 * DEG_TO_RAD;
        vector look_at = <llCos(angle), llSin(angle), 0>;

        if (current_region == global_coord) {
            look_at = region_pos + look_at;
        }

        llTeleportAgentGlobalCoords(llGetOwner(), global_coord, region_pos, look_at);
    }
}

 

For llTeleportAgent: You have to keep track of the landmark's global coordinate, and then calculate the total distance to the destination. This one is especially tricky to implement because the landmark's coordinate can either be a region-local coordinate like <100, 130, 40>, or a global coordinate + region-local offset like <-131704.6, -24381.2, 22.48>, depending on whether you're in the same sim or not.

string landmark;
vector destination;

default
{
    state_entry()
    {
        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

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

        if (llGetInventoryNumber(INVENTORY_LANDMARK) > 0) {
            landmark = llGetInventoryName(INVENTORY_LANDMARK, 0);
            llRequestInventoryData(landmark);
        }
    }

    dataserver(key query, string data)
    {
        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;
        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) {
            look_at = destination + look_at;
        }

        llTeleportAgent(llGetOwner(), landmark, ZERO_VECTOR, look_at);
    }
}

 

These examples cover a semi-common corner-case where the destination is something you will teleport to from multiple regions (including the destination itself). Without this kind of handling, you might arrive at the destination with the wrong orientation.

In the first script you can also use llGetRegionCorner() instead of waiting on dataserver replies from llRequestSimulatorData(llGetRegionName(),DATA_SIM_POS);

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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