Jump to content

Teleport Board issue


Syaoran Nyoki
 Share

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

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

Recommended Posts

Having an issue with a teleport board I am creating. I have a board with 45 landmarks inside it.

Each square on the board will have a hotspot (invisible Prim) in front of it. (see no 1)

 

Capture.PNG

So the control script is in the board itself. All variables in my script are filled properly, but the map never shows up. Is there is something about how to use llMapDestination?

 

key request;
string name;
string sim_name;
vector pos;
integer i;

default
{
state_entry()
{
llListen(777, "", "", "");
}

listen(integer channel, string name, key id, string message)
{
i = (integer)message;
if(llGetInventoryNumber(INVENTORY_LANDMARK))
{
name = llGetInventoryName(INVENTORY_LANDMARK,i-1);
request = llRequestInventoryData(name);
}
}

dataserver(key id, string data)
{
if(id == request)
{
pos = (vector)data;
sim_name = llGetRegionName();
llSay(0, "SimName is "+sim_name);
llSay(0, "Pos is "+(string)pos);

llMapDestination(sim_name, pos, pos);
}
}

}

Link to comment
Share on other sites

llMapDestination needs to be within a touch event for it to work properly. I'd suggest using just the texture on the board and within your script a touch_start event that determines where it was touched See llDetectedTouchFace (to determine if it is the front of the board being touched) and then use either http://wiki.secondlife.com/wiki/LlDetectedTouchST or http://wiki.secondlife.com/wiki/LlDetectedTouchUV (to determine where the touch took place) and then calling llMapDestination with the appropriate destination based on that.

 

That'll save a pocket full of prims, get rid of the listen and be easier to code as well.

  • Like 1
Link to comment
Share on other sites

I re-tooled this script using the advice of LepreKahn but now I have a new problem I haven't been able to solve.

I need the touch event to determine what part of the texture was touched and I need it to do llMapDestination. The problem lies when I read the landmark info. The variable pos is blank when I do llMapDestination. Anyone know a way around this?

 

Capture.PNG

 

key request;
string name;
string sim_name;
vector pos;
integer i;

integer numberOfRows = 9;
integer numberOfColumns = 5;

default
{

touch_start(integer total_number)
{
vector touchST = llDetectedTouchST(0);
integer columnIndex = llFloor(touchST.x * numberOfColumns);
integer rowIndex = llFloor(touchST.y * numberOfRows);
integer cellIndex = (rowIndex * numberOfColumns) + columnIndex;

// llSay(PUBLIC_CHANNEL, "ST (" + (string)columnIndex + ", " + (string)rowIndex + ") --> " + (string)cellIndex);

if (cellIndex >= 0 && cellIndex <= 5)
{
i = cellIndex + 40;
}
else if (cellIndex >= 5 && cellIndex <= 9)
{
i = cellIndex + 30;
}
else if (cellIndex >= 10 && cellIndex <= 14)
{
i = cellIndex + 20;
}
else if (cellIndex >= 15 && cellIndex <= 19)
{
i = cellIndex + 10;
}
else if (cellIndex >= 20 && cellIndex <= 24)
{
i = cellIndex;
}
else if (cellIndex >= 25 && cellIndex <= 29)
{
i = cellIndex - 10;
}
else if (cellIndex >= 30 && cellIndex <= 34)
{
i = cellIndex - 20;
}
else if (cellIndex >= 35 && cellIndex <= 39)
{
i = cellIndex - 30;
}
else if (cellIndex >= 40 && cellIndex <= 44)
{
i = cellIndex - 40;
}


if(llGetInventoryNumber(INVENTORY_LANDMARK))
{
name = llGetInventoryName(INVENTORY_LANDMARK,i);
llSay(0, "Landmark name = "+ name);
request = llRequestInventoryData(name);
}

llSay(0, "Position just before llMapDest = "+(string)pos);

llMapDestination(sim_name, pos, pos);
}

dataserver(key id, string data)
{
if(id == request)
{

pos = (vector)data;
llSay(0, "Position Dataserver = "+(string)pos);
sim_name = llGetRegionName();
}
}

}

Link to comment
Share on other sites

Yeah, the problem is that you're waiting until you get the touch_start() event to get the landmark's information, which will come in through that dataserver event, after the touch_start() handler has exited.

The way around this is to read and store in a list all the landmark info in advance. You can do this in a state_entry() handler, and perhaps also in changed() CHANGED_INVENTORY if those landmarks will be added without resetting the script.

  • Like 1
Link to comment
Share on other sites

I've been trying to load all the landmarks' position data into a list at state_entry(). Every way I try to do it, it just loads the list with the same position coordinates (for the first one it reads) 45 times. Does anyone know a way to do this that will read a new landmark after each append?

 

key request;
string name;
string sim_name;
vector pos;
integer i;
integer x;
list landmarks = [];
integer numberOfRows = 9;
integer numberOfColumns = 5;

default
{
state_entry()
{
request = llRequestInventoryData(llGetInventoryName(INVENTORY_LANDMARK, x));
}

touch_start(integer total_number)
{
vector touchST = llDetectedTouchST(0);
integer columnIndex = llFloor(touchST.x * numberOfColumns);
integer rowIndex = llFloor(touchST.y * numberOfRows);
integer cellIndex = (rowIndex * numberOfColumns) + columnIndex;

// llSay(PUBLIC_CHANNEL, "ST (" + (string)columnIndex + ", " + (string)rowIndex + ") --> " + (string)cellIndex);

if (cellIndex >= 0 && cellIndex <= 5)
{
i = cellIndex + 40;
}
else if (cellIndex >= 5 && cellIndex <= 9)
{
i = cellIndex + 30;
}
else if (cellIndex >= 10 && cellIndex <= 14)
{
i = cellIndex + 20;
}
else if (cellIndex >= 15 && cellIndex <= 19)
{
i = cellIndex + 10;
}
else if (cellIndex >= 20 && cellIndex <= 24)
{
i = cellIndex;
}
else if (cellIndex >= 25 && cellIndex <= 29)
{
i = cellIndex - 10;
}
else if (cellIndex >= 30 && cellIndex <= 34)
{
i = cellIndex - 20;
}
else if (cellIndex >= 35 && cellIndex <= 39)
{
i = cellIndex - 30;

else if (cellIndex >= 40 && cellIndex <= 44)
{
i = cellIndex - 40;


// llSay(0, "Position just before llMapDest = "+(string)pos);
llMapDestination(llGetRegionName(), llList2Vector(landmarks, i), llList2Vector(landmarks, i));
}

dataserver(key id, string data)
{
if(id == request)
{
do
{
pos = (vector)data;
name = llGetInventoryName(INVENTORY_LANDMARK, x);
llSay(0, name + " " + (string)pos);
landmarks += pos;
llSay(0,llList2String(landmarks, x)+ "x= " + (string)x);
request = llRequestInventoryData(name);
}
while(++x < llGetInventoryNumber(INVENTORY_LANDMARK));

}
}

}

Link to comment
Share on other sites

You're really close. The trick is to use the dataserver event to trigger the request for just the next landmark's data.

You could do it in a loop, but at scale, you can't just issue all the requests at once lest events get dropped, so you'd need to manage a fixed-length queue of outstanding requests.  That's inordinately complicated for this application, so it's easier to just do them one after another.

So, try this tweak of your current dataserver handler:

 

if(id == request){
    pos = (vector)data; name = llGetInventoryName(INVENTORY_LANDMARK, x); llSay(0, name + " " + (string)pos); landmarks += pos; if (++x < llGetInventoryNumber(INVENTORY_LANDMARK)) request = llRequestInventoryData(llGetInventoryName(INVENTORY_LANDMARK, x)); else llOwnerSay("Done reading landmarks");}

[EDIT: Oopsy. Added the pos = assignment that I omitted first time around.]

  • Like 1
Link to comment
Share on other sites

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