From: Icarus DuCasse
hey Newgate,
thanks for taking time to analyse. Really appreciated.
The problem which I found to arise was that if one got seated all scripts even if they're not in the root call the changed event so all scripts send their message again to the root. In consequence the list soon got overpopulated.
This script in one of the seats call the change event whenever an agent sits in the vehicle disregarding where it sits. Is it possible to do a check in this event whether the agent is seated/unseated on the local prim (prim with script)? I tried some things but failed.
Functions like llDetectedLinkNumber only detect the local prim number and not the one who started the change event? So Im pondering how to distinct change events ... without much result.
Any change to the link set will trigger a change event in each script that handles it. But its NOT a problem if you handle the code slightly differently. When ever anyone sits / unsits you just need to rebuild the complete list from scratch. Your seat scripts DONT need any real intelligence apart from to only pass on their current sitter's details if sat on. Then in the main script you store the name, key and the prim it came from.
You could use a strided list but personally I would use three lists, its just a little bit simpler.
When your menu is used you will get back the name, you use this to find its index and then from that look up the prim number. You then send that prim number an UNSEAT message.
Seat Script
// Seat Script -
// Define constants where possible
integer SEATED = 1000;
integer UPDATEME = 1001;
integer UNSEAT = 9999;
default
{
state_entry()
{
llSitTarget(<-.38, -.02, 2>, <0,0,-1.0,1>);
}
link_message(integer sender_num, integer num, string str, key id)
{
if(UPDATEME == num)
{
// EDIT ----------- BUG FIX
key currentid =llAvatarOnSitTarget();
if(currentid != NULL_KEY)
{
string name = llKey2Name(currentid );
llMessageLinked(LINK_ROOT,SEATED, name, currentid );
}
// END EDIT ----------- BUG FIX
}
else if(UNSEAT == num)
{
// Double check!
key currentid =llAvatarOnSitTarget();
if(currentid == id) llUnSit(id);
}
}
}
Main Script (INCOMPLETE CODE)
list Names;
list Keys;
list Prims;
// Define constants where possible
integer SEATED = 1000;
integer UPDATEME = 1001;
integer UNSEAT = 9999;
ClearAllLists()
{
Names = [];
Keys = [];
Prims = [];
}
AddName(integer sender_num, string str, key id)
{
Names = (Names = []) + Names + [ str ];
Keys = (Keys = []) + Keys + [ id ];
Prims = (Prims = []) + Prims + [ sender_num ];
}
default
{
state_entry()
{
llSitTarget(<-.38, -.02, 2>, <0,0,-1.0,1>);
ClearAllLists();
}
changed(integer change)
{
if(change & CHANGED_LINK)
{
ClearAllLists();
key id =llAvatarOnSitTarget();
if (id)
{
string name = llKey2Name(id);
AddName(LINK_ROOT,name,id);
llMessageLinked(LINK_SET,UPDATEME, name, id);
}
}
}
link_message(integer sender_num, integer num, string str, key id)
{
if(SEATED == num)
{
AddName(sender_num, str, id);
Names = (Names = []) + Names + [ str ];
Keys = (Keys = []) + Keys + [ id ];
Prims = (Prims = []) + Prims + [ sender_num ];
}
}
listen( integer channel, string name, key id, string message )
{
// Clear down the listen
// CancelListen();
integer index = llListFindList( Names , [ message ] );
if(index >= 0)
{
key target = llList2Key( Keys , index );
integer linknumber = llList2Integer( Prims , index);
if(LINK_ROOT == linknumber)
{
key currentid =llAvatarOnSitTarget();
if(currentid == target) llUnSit(target);
}
else
{
llMessageLinked(linknumber,UNSEAT, name, target);
}
}
}
}
Obviously I've left out the invoking of the dialog.
The above is untested but I think its ok.
You could simplify the main Script Code code slightly more by having a seat script in the root prim as well and handling it exactly like all the other seats. I'll leave that for you to decide.
HtH