Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Online Status in Linked Set

Dmitriy Gausman
Registered User
Join date: 16 May 2007
Posts: 132
05-03-2009 08:59
I have a welcome board for when people come to our SIMs, they can contact any of the online reps of the sim should they need help. The board has pictures of each rep, which turns on and off (full bright) depending on there online status.

Originally, the script was using llKey2Name to check if a rep was on one of the SIMS, but it was not very reliable, so I decided a normal online check would be fine, regardless of whether the rep is on the SIMS or not.

The root of the board has the main script and there are linked objects that have pictures of each rep (in the contents of the object) as well as their avatar key (in a notecard).

A person touches the board and a standard message is sent to all online reps.

This is the script for each linked object (one per representative). I am struggling where to do the llRequestAgentData(welcomer_key, DATA_ONLINE without additional dataserver calls (state available, state not_available). Where I get lost is that once the initial state is determined, I need to check to make sure the reps online status has not changed before each call is sent.

I apologize for the mess. Any help would be greatly appreciated.


CODE

integer channel;
string welcomer_name;
key welcomer_key;
key queryID;
float time_gap = 60;

vector def_tex_repeats = <1.0, 1.0, 0.0>;
vector def_tex_ofsets = <0.0, 0.0, 0.0>;
key def_texture;
list portrait_params;


set_welcomer_portrait() {
string portrait = llGetInventoryName(INVENTORY_TEXTURE, 0);
if(llGetInventoryNumber(INVENTORY_TEXTURE) == 0) {
llSetPrimitiveParams([
PRIM_TEXTURE,
0,
def_texture,
def_tex_repeats,
def_tex_ofsets,
0.0
]);
} else {
portrait_params = llGetPrimitiveParams([PRIM_TEXTURE,0]);
llSetPrimitiveParams([
PRIM_TEXTURE,
0,
portrait,
llList2Vector(portrait_params,1),
llList2Vector(portrait_params,2),
llList2Float(portrait_params,3)
]);
}
}

integer set_welcomer_name() {
if(llGetInventoryNumber(INVENTORY_NOTECARD)>0) {
welcomer_name = llGetInventoryName(INVENTORY_NOTECARD,0);
llSetObjectName("WELCOME MESSENGER of " + welcomer_name);
if(llGetSubString(llGetObjectDesc(), 0, 0) != "<") {
llSetObjectDesc((string)def_tex_repeats + (string)def_tex_ofsets);
}
set_welcomer_portrait();
return TRUE;
} else {
llSetObjectName("Welcomer");
llSetObjectDesc("Messenger v1");
set_welcomer_portrait();
return FALSE;
}
}

default {
on_rez(integer start_param) {
llResetScript();
}

state_entry() {
llSetText( "Initilizing...", <1, 1, 1>, 1 );
llSetPrimitiveParams([
PRIM_FULLBRIGHT, 0, TRUE,
PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 1.0
]);
llMessageLinked(LINK_ROOT, 0, "channel", "");
}

link_message (integer sender_num, integer num, string message, key def_tex) {
def_texture = def_tex;
if (sender_num == LINK_ROOT) {
channel = num + (integer)message;
}

if(set_welcomer_name()) {
queryID = llGetNotecardLine(welcomer_name, 0);
} else {
state empty;
}
}

dataserver(key query_id, string data) {
if (query_id == queryID) {
welcomer_key = (key)data;
if (llRequestAgentData(welcomer_key, DATA_ONLINE)) {
state available;
} else {
state not_available;
}
}
}


state_exit() {
llSetPrimitiveParams( [PRIM_FULLBRIGHT, ALL_SIDES, FALSE] );
}
}

state empty {
on_rez(integer start_param) {
llResetScript();
}

state_entry() {
llSetText( "", <1, 1, 1>, 1 );
llSetPrimitiveParams([
PRIM_FULLBRIGHT, ALL_SIDES, FALSE,
PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0
]);
}

changed(integer change) {
if (change & CHANGED_INVENTORY) {
state default;
}
}

link_message(integer sender_num, integer num, string str, key id) {
if(sender_num==LINK_ROOT && str=="Reset all") {
state default;
}
}
}

state available {
on_rez(integer start_param) {
llResetScript();
}
state_entry() {
llSetTimerEvent( time_gap );
llSetPrimitiveParams([PRIM_FULLBRIGHT, 0, TRUE]);
}


timer() {
//[check here to see if the avatar went offline]
llSetPrimitiveParams([PRIM_FULLBRIGHT, ALL_SIDES, FALSE]);
state not_available;
}
}

changed(integer change) {
if (change & CHANGED_INVENTORY) {
state default;
}
}

link_message(integer sender_num, integer num, string str, key id) {
if(sender_num==LINK_ROOT && str=="Reset all") {
state default;
} else if(sender_num==LINK_ROOT && num==1) {
llInstantMessage ( welcomer_key, "\n>>>>>>>> " + str + "<<<<<<<<\n" );
}
}

state_exit() {
llSetTimerEvent( 0 );
}
}

state not_available {
on_rez(integer start_param) {
llResetScript();
}

state_entry() {
llSetTimerEvent( time_gap );
llSetPrimitiveParams([PRIM_FULLBRIGHT, ALL_SIDES, FALSE]);
}

timer() {
//[check here to see if the avatar came online]
llSetPrimitiveParams([PRIM_FULLBRIGHT, ALL_SIDES, TRUE]);
state available;
}
}

changed(integer change) {
if (change & CHANGED_INVENTORY) {
state default;
}
}

link_message(integer sender_num, integer num, string str, key id) {
if(sender_num==LINK_ROOT && str=="Reset all") {
state default;
}
}

state_exit() {
llSetTimerEvent( 0 );
}
}
CODE
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
05-04-2009 04:07
I'm not sure if this is going to wholly answer your question. Your script has quite a lot going on so I kinda gave up with it. :) Instead, here's something a little more simplistic. It does, however, have its logic being controlled via the dataserver Event (which is mainly what I was trying to demonstrate).

It's a lot simpler than your offering but I don't see why you couldn't replace the touch_start with link_message, and tweak the dataserver to suit your specific needs. What it doesn't have is lots of states - but maybe that's an advantage. :D

Just rez a cube and drop the script inside.

CODE

string oName;
key oKey;
key oQueryid;

string vName;
key vKey;
integer vRequest;

init()
{
oKey = llGetOwner();
oName = llKey2Name(oKey);
llSetPrimitiveParams([PRIM_ROTATION, <0.5, 0.5, 0.5, 0.5>]);
llSetTexture("8be8e2d8-239c-dd23-88fa-5b82352be71b", 0);
oQueryid = llRequestAgentData(oKey, DATA_ONLINE);
llSetTimerEvent(60);
}

default
{
touch_start(integer num_detected)
{
vKey = llDetectedKey(0);
vName = llKey2Name(vKey);
vRequest = 1;
oQueryid = llRequestAgentData(oKey, DATA_ONLINE);
}

dataserver(key queryid, string data)
{
if (queryid == oQueryid)
{
if (data == "1")
{
llSetPrimitiveParams([PRIM_FULLBRIGHT, 0, TRUE,
PRIM_COLOR, 0, <1.0, 1.0, 1.0>, 1.0]);
llSetText(oName + " is Online", <1.0, 1.0, 1.0>, 1.0);
if (vRequest)
{
llInstantMessage (oKey, vName + " is calling you." );
llInstantMessage (vKey, oName + " has been paged. Stand by.");
}
}
else
{
llSetPrimitiveParams([PRIM_FULLBRIGHT, 0, FALSE,
PRIM_COLOR, 0, <0.25, 0.25, 0.25>, 1.0]);
llSetText(oName + " is Offline", <0.0, 0.0, 0.0>, 1.0);
if (vRequest) llInstantMessage (vKey, oName + " is not available right now." );
}

vRequest = 0;
}
}

timer()
{
oQueryid = llRequestAgentData(oKey, DATA_ONLINE);
}

state_entry()
{
init();
}

on_rez(integer start_param)
{
init();
}
}
_____________________
Dmitriy Gausman
Registered User
Join date: 16 May 2007
Posts: 132
05-06-2009 09:19
I am working on changing the board now. Rather than go with multi linked objects that each contain the UUID of the avatar, I am going to try and use a notecard with all the UUIDS of the representatives. Then have the script make a list from the notecard, so when the user touches the call button, all UUID's in the list will be checked for online status and if online, the message will be sent to them that someone needs help. To accomodate the representatives need to have their picture on the board, we'll just slap their photo onto a non scripted prim.

I just need to learn more about looping through the list I made from the notecard so I can check each representatives online status.

Thank you for the reply. You motivated me to simplify it.
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
05-06-2009 10:00
This script is not complete, but assuming the list 'Keys' is populated somehow... here's a dataserver-driven loop:

CODE

list keys;
integer count;

default
{
touch_start(integer num_detected)
{
count = 0;
llRequestAgentData(llList2Key(keys, count), DATA_ONLINE);
}

dataserver(key queryid, string data)
{
if (data == "1") llOwnerSay(llKey2Name(llList2Key(keys, count)) + " is online");

if (count < llGetListLength(keys) - 1)
{
count++;
llRequestAgentData(llList2Key(keys, count), DATA_ONLINE);
}
}
}


The trick is to allow the dataserver Event to increment the loop.
_____________________
Dmitriy Gausman
Registered User
Join date: 16 May 2007
Posts: 132
05-07-2009 07:25
I am getting lost on how to proceed to the step after my list is made.

The notecard of the greeters (representatives) has information that looks like this. The names are included here to make it easier to remove a person should they no longer be a greeter:
CODE

Tara Marinara,414f4bc1-e133-61f3-8c75-5fff1234414e
Nino Cappuccino, ed1182f7-4a31-38d4-ecd6-3f1b8c9d5a36
CODE


The script needs to do two things. Read the notecard to get a list of the greeter UUIDS and then when a person comes to touch the board, go through the greeter UUID list, and any online greeter UUID will get sent a message. The greeter UUID's offline will not.

I can't get two dataserver calls within the same state (I think). I didn't think it would be efficient to make a list of UUID's each time there is a touch event. But maybe I don't need a list sitting in memory. I could wait for the touch, then pull the UUID's from the notecard, check their online status as I go through each line of the notecard, and send a message. That would require having an llGetNotecardLine and a lRequestAgentData together. Not sure if that is even possible.

I am sure this is a mess, but this is what I have so far. It does seem to read the notecard well, so I am thankful for a small victory.

CODE

//initialization variables
string config_notecard = "Greeters";
integer nLine;
key QueryID;

//dataserver variables
list temp;
string greeter_key;
string greeter_name;
list greeter_list;
string greeter_keys;
list newlist;


default
{
state_entry()
{
llOwnerSay("Initializing…");

if (llGetInventoryType(config_notecard) == INVENTORY_NOTECARD)
{
QueryID = llGetNotecardLine(config_notecard, nLine );
}
else
{
llOwnerSay("Configuration notecard not found!");
state end_program;
}
}

dataserver( key queryid, string data )
{
if (queryid == QueryID)
{
if (data != EOF)
{
temp = llCSV2List(data);
greeter_key = llList2String(temp,1);
++nLine;
QueryID = llGetNotecardLine(config_notecard, nLine);
newlist += greeter_key;
}
else
{
llOwnerSay("Done.");
llWhisper(0,"Greeter List is: " + llList2CSV(newlist));
}
}
}
}
state end_program
{
state_exit()
{
llWhisper(0,"Shutting Down");
}
}
CODE
Dmitriy Gausman
Registered User
Join date: 16 May 2007
Posts: 132
05-07-2009 22:57
I am slightly less confused now and made some good progress. Just a few things to fix and it should be good.
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
Mixing different types of data server request
05-08-2009 02:56
You can indeed have more than one flavour of dataserver request in the same state. The queryid parameter in the dataserver Event handler can be used to differentiate between the various dataserver requests.

Consider these two requests:

dolQueryId = llRequestAgentData(llList2Key(keys, count), DATA_ONLINE);;
gnlQueryID = llGetNotecardLine(config_notecard, nLine);

...notice we now have two different queryid variables. These can be used in the dataserver Event handler:


CODE


dataserver(key queryid, string data)
{
if (queryid == dolQueryId)
{
// data-online code
if (count < llGetListLength(keys) - 1)
{
count++;
llRequestAgentData(llList2Key(keys, count), DATA_ONLINE);
}
}

else if (queryid == gnlQueryId)
{
if (data != EOF)
{
// notecard line code
nLine++;
gnlQueryID = llGetNotecardLine(notecard, nLine);
}
}
}

_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
05-08-2009 04:31
you can also do them sequentially with a single query ID ceck variable, and a single counter, by using positive line for the notecard reading section (zero to EOF), then negative indexes for the agent data requests from list (-list lengength to -1).
CODE

dataserver( :: stuff :: ){
if (stored_key == queryID){
if (counter > 0){
//-- agent data stuff
if (++counter){
//-- request the next agent data look up
}
}else{
if (EOF != data){
//-- notecard stuff
//-- get note line ++counter
}else{
//-- request first agent data look up (counter = -listlength)
}
}
}
}

reusable variables are good.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -