Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Store location Before teleport

Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 08:31
ok, so i'm trying to grab my location prior to a teleport function, but i keep running into hiccups of either not grabbing the location, or grabbing the location i go to, not the one i was at prior. any help would be greatly appreciated.

CODE

string hist_parcel;
string hist_sim;
vector hist_pos;

vector vec_round(vector a) {
a.x = (integer)a.x;
a.y = (integer)a.y;
a.z = (integer)a.z;

return a;
}

string parcel_name(){
list parcel = llGetParcelDetails(llGetPos(), [PARCEL_DETAILS_NAME]);
return llList2String(parcel, 0);
}

current_location() {
if (parcel_name() == hist_parcel) {
if (llVecDist(vec_round(llGetPos()), vec_round(hist_pos)) > 50) {
hist_pos = vec_round(llGetPos());
}
}
else if (llGetRegionName() == hist_sim){
if (llVecDist(vec_round(llGetPos()), vec_round(hist_pos)) > 10) {
hist_pos = vec_round(llGetPos());
}
}
else {
hist_parcel = parcel_name();
hist_sim = llGetRegionName();
hist_pos = vec_round(llGetPos());
}
}

string store_hist() {
string hist_pos_temp = (string)hist_pos;
string hist_sim_temp = hist_sim;
hist_pos_temp = str_replace("<", " (", hist_pos_temp);
hist_pos_temp = str_replace(".00000>", ")", hist_pos_temp);
hist_pos_temp = str_replace(".00000,", ",", hist_pos_temp);
string hist_string = hist_parcel + ", " + hist_sim_temp + hist_pos_temp;
return hist_string;
}

default
{
state_entry()
{
hist_pos = vec_round(llGetPos());//returns a rounded up and
hist_sim = llGetRegionName();
hist_parcel = parcel_name(); //returns parcel name, or "no name" if none
llSetTimerEvent(5);
}

timer() {
current_location();
}

changed(integer change) {
if (change & CHANGED_TELEPORT) {
llSetTimerEvent(0);//set timer to 0 to keep values from changing till storage is executed
store_hist();
llSetTimerEvent(5);//re-enstate timer
}
}
}


i have tried different timer settings, with some success with longer waiting times, but then the results get less accurate if you say, move in between timer calls after using a sit teleporter and have been moved to a different location. that new location would miss getting saved.

next question:
anyone know how to round a vector and not end up when all those trailing zeros?

and yes, i know i doing alot in the store_hist function with all the string formating and typecasting, but there is a reson, i swear =)
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 08:44
The changed event isn't always processed before teleporting, it depends on how busy the sim is. So if you're in a busy sim and you teleport, then changed event will be processed when you arrive at the other end, rather than before you teleport.
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 08:49
Maybe round your vector something like this?:

vector v=llGetPos();

integer x=(integer)v.x
integer y=(integer)v.y
integer z=(integer)v.z

v=<x,y,z>;
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 08:51
From: 2k Suisei
The changed event isn't always processed before teleporting, it depends on how busy the sim is. So if you're in a busy sim and you teleport, then changed event will be processed when you arrive at the other end, rather than before you teleport.


thanks for that 2K.
so really, increasing the llTimerEvent() is the only real way to increase likely hood of getting the correct location? but even a timer time of 10 seconds could fail that logic, due to the teleports that take forever sometimes. guees it's stil something i'm able to live with, as long as most of my locations are correct, lol.

i'll be sure to test out that vector formating as soon as the grid's back up, though it passes compilation, thanks again

I so wish we had a way to 'hook' inherent SL functions to grab info.... WoW coding sppoiled me sooo much, lol feeling all sorts of nostalgic for Lua
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 09:03
From: Elsewhere Essex
thanks for that 2K.
so really, increasing the llTimerEvent() is the only real way to increase likely hood of getting the correct location? but even a timer time of 10 seconds could fail that logic, due to the teleports that take forever sometimes. guees it's stil something i'm able to live with, as long as most of my locations are correct, lol.

i'll be sure to test out that vector formating as soon as the grid's back up, though it passes compilation, thanks again

I so wish we had a way to 'hook' inherent SL functions to grab info.... WoW coding sppoiled me sooo much, lol feeling all sorts of nostalgic for Lua


something like this inside your changed event should fix it:

llSleep(2);
StoreHist();

This will help to make sure the history is stored after arriving.
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 09:13
Also, I guess you only want to round your vector down for display purposes. It's probably best to round it down and convert it to a string just prior to outputting, because I'm sure SL will still insist on adding a .0 to rounded vector values anyway.
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
12-13-2006 10:37
I wouldn't bother to do the rounding till you actually need to store it.

CODE


string pos_string(vector v)
{
return( "( " + (string)llRound(v.x) + ","
+ (string)llRound(v.x) + ","
+ (string)llRound(v.x) + " )";
}

...
hist_pos = llGetPos();
...
string hist_pos_temp = pos_string(hist_pos);
...


As for the history problem, I'd keep a list of say, the last 5 locations, and then backtrack to the last one in previous region after teleport. Also, there is no need to turn off the timer during the changed() event, it won't interrupt. You never receive the teleport event before teleporting (oh, for some warning!) but it's possible for the timer event to trigger first. Also remember, you are not guaranteed to be in a new region or parcel after the teleport event. I can post some working code later when SL is back up.
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 10:43
From: 2k Suisei
something like this inside your changed event should fix it:

llSleep(2);
StoreHist();

This will help to make sure the history is stored after arriving.

not sure about that one since sleeping after teh teleport calls, still leaves time for the location to be overwritten with teh fresh location if teleport events doesn't fire till you arrive from that Teleport event.

i may just have to store the locations twice, as a curret_loc and previous_loc on each timer event. previous_loc being the previous current_loc.

then on CHANGED_TELEPORT, compare where i am now to current_loc. if they too close to each other after a RegionName and VecDist check, store previous_loc, if not, store current_loc and re-enstate teh timer.

in response to Boss: are you sure about the teleport only firing after you arrive? if LSL is a single threaded scripting envronment, then the correct location should have been being stored, since, durring the execution of my code in the changed event, timer gets queued till after that code block stores the location i was at before teleporting. that was not the results i was expiriencing in world. although, the thought that timer still fires durring the telport screen, while CHANGED_TELEPORT doesn'ttill you get your game back, would explain it. wonder if that is the case.
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
12-13-2006 11:09
From: Elsewhere Essex
in response to Boss: are you sure about the teleport only firing after you arrive? if LSL is a single threaded scripting envronment, then the correct location should have been being stored, since, durring the execution of my code in the changed event, timer gets queued till after that code block stores the location i was at before teleporting. that was not the results i was expiriencing in world. although, the thought that timer still fires durring the telport screen, while CHANGED_TELEPORT doesn'ttill you get your game back, would explain it. wonder if that is the case.


There is a chance that the timer event can fire before the changed event, causing your new location to be stored before the change event takes place... but you can't be notified of a change (e.g. teleport) until the change has happened. The timer event is queued, but the results of llGetPos() etc. are not of course.

~Boss
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
12-13-2006 11:09
One more note: Sleeping does not yield to other events.
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 11:15
From: Boss Spectre
... As for the history problem, I'd keep a list of say, the last 5 locations, and then backtrack to the last one in previous region after teleport. Also, there is no need to turn off the timer during the changed() event, it won't interrupt. You never receive the teleport event before teleporting (oh, for some warning!) but it's possible for the timer event to trigger first. Also remember, you are not guaranteed to be in a new region or parcel after the teleport event. I can post some working code later when SL is back up.

that's a good idea, though for the type of dynamic data that parcel name, sim name, and position data storage would be, it seems like it woud need to be at the very least, for five locations, it would be fifteen list entries, and index referenced in groups of three.
["parcel 1", "sim 1", "vector 1", "parcel 2", "sim 2", "vector 2",......]
only way i can think to store the data for comparative functions
so after convertig the list info,
CODE
list old_locs = ["parcel 1", "sim 1", "vector 1", "parcel 2", "sim 2", "vector 2",......];
integer a = llListFindList(old_locs, [currentparcel, currentregion, currentvectorrounded]);
if (a != -1){
do_somthing with old_loc at indexes a -3 through a - 1
else {
do_something with old_loc at indexes listlength - 4 through listlength - 1
}


as far as Teleport working with in the same sim/parcel, do you mean if they are in the same place as their home and tp home?or does CHANGED_TELEPORT still fire even on a failed teleport? coulda sworn that trying to tele to a location in teh sim you are in results in the "location too close" message
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 11:24
From: Elsewhere Essex
not sure about that one since sleeping after teh teleport calls, still leaves time for the location to be overwritten with teh fresh location if teleport events doesn't fire till you arrive from that Teleport event.

.


The llSleep() is a way of making sure the following code is executed after the person has arrived at their destination. The event would then store the previous sim's name.


You could always just scrap the change event and check for a sim change in your timer event.

if (llGetRegionName()!=CurrentSimName)
{
Store_Hist();
CurrentSimName=llGetRegionName();
}

Or is it essential you only capture teleports?
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 11:36
From: 2k Suisei
The llSleep() is a way of making sure the following code is executed after the person has arrived at their destination. The event would then store the previous sim's name.


You could always just scrap the change event and check for a sim change in your timer event.

if (llGetRegionName()!=CurrentSimName)
{
Store_Hist();
CurrentSimName=llGetRegionName();
}

Or is it essential you only capture teleports?

I was really only after teleportsand grabbing locations teleported from, instead of the far easier to code, locations teleported to, lol.

Bosses list suggestion seems like the most fruitful route for me to pursue since storing multiple locations in the way alows more failsafe.
2k Suisei
Registered User
Join date: 9 Nov 2006
Posts: 2,150
12-13-2006 11:39
From: Elsewhere Essex
I was really only after teleportsand grabbing locations teleported from, instead of the far easier to code, locations teleported to, lol.

Bosses list suggestion seems like the most fruitful route for me to pursue since storing multiple locations in the way alows more failsafe.



You don't have to store the location teleported to. You store the location teleported from! :)
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-13-2006 14:29
CODE
list old_locs = ["parcel 1", "sim 1", "vector 1", "parcel 2", "sim 2", "vector 2",......];
integer a = llListFindList(old_locs, [currentparcel, currentregion, currentvectorrounded]);
if (a != -1){
do_somthing with old_loc at indexes a -3 through a - 1
else {
do_something with old_loc at indexes listlength - 4 through listlength - 1
}

this is working the best so far, along with the other stuff i have in there to make sure you are acertain vector distance from your last timer based location scan and a timer of 2.
only misfires 1 out of every 20 teleports so far, and even then, only in extremely laggy sims... may have to base the timers on server time dilation.
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
code to track location before teleport
12-14-2006 08:45
Give this script a try:

CODE

float SCAN_RATE = 5.0;
integer STRIDE = 3;
integer STRIDE_END = 2;
integer MAX_HIST = 4;
list history;

string loc_string(vector v) {
return "( " + (string)llFloor(v.x) + ","
+ (string)llFloor(v.y) + ","
+ (string)llFloor(v.z) + " )";
}

string hist_parcel;
string hist_sim;
vector hist_pos;

vector vec_round(vector a) {
a.x = (integer)a.x;
a.y = (integer)a.y;
a.z = (integer)a.z;

return a;
}

string parcel_name(){
list parcel = llGetParcelDetails(llGetPos(), [PARCEL_DETAILS_NAME]);
return llList2String(parcel, 0);
}

current_location() {
integer index = llGetListLength(history) / STRIDE;
if (index >= MAX_HIST)
index = 1;
else
index = 0;
history = llList2List(history, index * STRIDE, -1) +
[parcel_name(), llGetRegionName(), llGetPos()];
}

string store_hist() {
integer index = llListFindList(history, [parcel_name()]);
if (index < 0) index = 0; // if no match, point to beginning (wraps to end)
index -= STRIDE; // negative numbers will seek backwards from list end

return llList2String(history, index) + ", "
+ llList2String(history, index + 1) + " "
+ loc_string(llList2Vector(history, index + 2));
}

default
{
state_entry()
{
llSetTimerEvent(0.01); // semi-immediate timer event
llSleep(0.1); // queue it up
llSetTimerEvent(SCAN_RATE); // the regular rate
}

on_rez(integer parameter)
{
if (llGetListLength(history) > 0)
llOwnerSay ("You were last at " + store_hist());
}

timer() {
current_location();
}

changed(integer change) {
if (change & CHANGED_TELEPORT) {
llOwnerSay ("I think you came here from " + store_hist());
}
}
}


This uses a short list to remember where it was last. It scans for the current parcel name and uses the one before it (in case it was recorded after teleport and before the changed event), or the last one on the list if the current name is not found.
~Boss
Geuis Dassin
Filming Path creator
Join date: 3 May 2006
Posts: 565
12-14-2006 14:41
Simple is better. Drop this into a prim. Wear the prim as an attachment.
I wrote this entirely in the forum post (no SL at work) so there could be a typo here or there. However, the form of the code should be good and work. I will try it at home soon and fix any problems.

Geuis

CODE

//Code by Geuis Dassin
//12-14-06
//Free for public use, free to modify and improve, free for commercial use.
//This statement must be contained with any section of this code that is used.

//START SCRIPT
string old_sim_name;
string new_sim_name;
vector old_sim_local_coordinates;
vector new_sim_local_coordinates;
vector old_sim_global_coordinates;
vector new_sim_global_coordinates;

default{

changed(integer change) { // something changed
if (change & CHANGED_TELEPORT) { // and it was a teleport change
//assign the variables for the location at the previous teleport
old_sim_name = new_sim_name;
old_sim_local_coordinates = new_sim_local_coordinates;
old_sim_global_coordinates = new_sim_global_coordinates;

//assign the variables for the new location
new_sim_name = llGetRegionName();
new_sim_local_coordinates = llGetPos();
new_sim_global_coordinates= llGetRegionCorner();
}
}

touch_start(integer num_detected){
llOwnerSay("Last Sim Name: " + old_sim_name + "Last Avatar Coordinates: "+ (string)old_sim_local_coordinates + "Last Sim Global Coordinates: "+ (string)old_sim_global_coordinates );
}
}
Elsewhere Essex
Registered User
Join date: 8 Sep 2006
Posts: 50
12-14-2006 17:23
From: Geuis Dassin
Simple is better. Drop this into a prim. Wear the prim as an attachment.
I wrote this entirely in the forum post (no SL at work) so there could be a typo here or there. However, the form of the code should be good and work. I will try it at home soon and fix any problems.

Geuis

CODE

//Code by Geuis Dassin
//12-14-06
//Free for public use, free to modify and improve, free for commercial use.
//This statement must be contained with any section of this code that is used.

//START SCRIPT
string old_sim_name;
string new_sim_name;
vector old_sim_local_coordinates;
vector new_sim_local_coordinates;
vector old_sim_global_coordinates;
vector new_sim_global_coordinates;

default{

changed(integer change) { // something changed
if (change & CHANGED_TELEPORT) { // and it was a teleport change
//assign the variables for the location at the previous teleport
old_sim_name = new_sim_name;
old_sim_local_coordinates = new_sim_local_coordinates;
old_sim_global_coordinates = new_sim_global_coordinates;

//assign the variables for the new location
new_sim_name = llGetRegionName();
new_sim_local_coordinates = llGetPos();
new_sim_global_coordinates= llGetRegionCorner();
}
}

touch_start(integer num_detected){
llOwnerSay("Last Sim Name: " + old_sim_name + "Last Avatar Coordinates: "+ (string)old_sim_local_coordinates + "Last Sim Global Coordinates: "+ (string)old_sim_global_coordinates );
}
}


thanks Geuis, but that store were you went after teleport not where you came from.
a problem i've since solved, thanx for the input everyone.
the list of last locations was the best bet, and what works for now.