Jump to content

Teleport Board issue


You are about to reply to a thread that has been inactive for 2693 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 post
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 post
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 post
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 post
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 post
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 post
Share on other sites
You are about to reply to a thread that has been inactive for 2693 days.

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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...