Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Reading lines on a notecard when conditions met?

Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
11-14-2005 21:40
I've been pouring over the wiki and can't seem to figure out how to call a dataserver function when a certain set of conditions are met. The conditions for making that call are calculated in a timer function, and I can't seem to call the dataserver function within the timer event, so my intuition on how to go about assembling it fails me.
Cid Jacobs
Theoretical Meteorologist
Join date: 18 Jul 2004
Posts: 4,304
11-14-2005 23:54
Sounds like you may be looking for if-else statements . Hope that helps, good luck. :)
_____________________
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
11-15-2005 03:46
From: Senuka Harbinger
and I can't seem to call the dataserver function within the timer event,
can you post a code snippet?
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
11-15-2005 05:04
You may have to transfer code from the timer event into the dataserver event, and store any variables globally so the dataserver has access to them. As ALL the code in a timer will execute BEFORE the dataserver event is called. e.g -

CODE
// State and global variables up here (line and lineNo are global)

timer() {
++lineNo;
llGetNotecardLine("note",lineNo);
if (lineNo == 1) {
if (line == "foo") {
// Do stuff
}
}
}

dataserver (string data) {
line = data;
}


What you'd have to do is something like this:

CODE
// State and global variables up here (lineNo is a global)

timer() {
++lineNo;
llGetNotecardLine("note",lineNo);
}

dataserver (string data) {
if (lineNo == 1) {
if (data == "foo") {
// Do stuff
}
}
}


This example would request a new notecard line every time the timer comes up (e.g every 10 seconds) and do something to it depending one what that line contains. So if the line is 1 and it reads "foo" then something happens.

In the first example the dataserver assigns the value to line, but since the event isn't called until AFTER the timer is finished, the value of data won't be assigned to line until it's time for the next attempt, at which point we're no longer interested in line 1.
Gaz Hornpipe
Registered User
Join date: 29 Sep 2005
Posts: 36
11-15-2005 09:07
The big problem when working with the dataserver is that it works independently from your script.. that is, you can't rely on it returning the information, in this case a notecard line, within the same timeframe each and every time. If you asked for the name of the object with llGetObjectName(), you would have the return of the information immediately before the next line of code. If you have llGetNotecardLine(), you won't get the return of the notecard line immediate before the next line of code, as the script will continue to run without waiting for the dataserver event.

Currently there is no real way for a script to pause/wait for the dataserver event to trigger before continuing, so you have to basically do what the last person said.

CODE
string gCard = "note";
integer gLine = 0;
integer count = 1;
list settings;

default
{
state_entry()
{
llSetTimerEvent(5.0);
}

timer()
{
count++;
if(count == 12) // 12 * 5 seconds = 60 seconds.
{
count = 1; // Reset counter
llSetTimerEvent(0); // Turn off timer for now
gLine = 0;
llGetNotecardLine(gCard,gLine); // Read notecard
}
}

dataserver(key queryID, string data)
{
if(data != EOF) // if not at End of File yet
{
if(data != "") // if notecard line is not blank
{
settings += data; // do whatever needs to be done with the notecard info
}
gLine++;
llGetNotecardLine(gCard,gLine); // grab the next line while not EOF
}
else
{
// Have finished reading the notecard...
llSetTimerEvent(5.0); // Start the timer again
}
}
}


Basically you reach a certain point in the script and then you have to wait for input.. except that instead of waiting for input from the user, you are waiting or input from another external source: the dataserver. If you only want to read a single notecard line and you know the line number of the notecard to read, then you can simplify the dataserver event..

CODE
    timer()
{
count++;
if(count == 12) // 12 * 5 seconds = 60 seconds.
{
count = 1; // Reset counter
llSetTimerEvent(0); // Turn off timer for now
gLine = 0; // whichever line you want to read from notecard
llGetNotecardLine(gCard,gLine); // Read line from notecard
}
}

dataserver(key queryID, string data)
{
settings = data; // do whatever needs to be done with the notecard line
llSetTimerEvent(5.0); // Start the timer again
}
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
11-15-2005 09:19
Thanks for the help, I managed to get some help in game as well to get what I need finally

here's the code so far (nowhere close to finished for the final product)

CODE

string notecard = "Waypoints";
integer current_noteline = 0;
integer current_target = -1;
integer listener;
list locations;
list descriptions;
string passed_text;

PointToTarget() { //This is what controls the pointer to point towards the next waypoint. since waypoints might cross sim boundaries (ie, a cross country road race), I elected to use global coordinates
if (llGetAttached() == 0) { llSetRot(ZERO_ROTATION); }
else {
vector gpos = llGetRegionCorner() + llGetPos(); //global position of the person wearing the HUD attachment
vector target = llList2Vector(locations,current_target); //global position of the waypoint, as listed on the notecard
rotation rot = llRotBetween(<0,0,1>,llVecNorm(target-gpos)); //Converts the vector used to point at the waypoint into a rotation
llSetRot(rot/llGetRot()); //rotates the pointer to the waypoint.
}
}

default {
state_entry() {
llSetRot(ZERO_ROTATION); //resets the pointer
llGetNotecardLine(notecard,current_noteline); //reads the 1st waypoint off the notecard
}
attach(key id) { llResetScript(); } //not too sure what's going on here aside from it counts the number of waypoints and returns them to the user.
dataserver(key qid, string data) {
if (data == EOF) {
llInstantMessage(llGetOwner(),(string)current_noteline+" locations loaded into memory.");
state wait;
}
else {
current_noteline++;
list words = llParseString2List(data,[" //","//"],[]);
//hack - llList2Vector returned NULL_VECTOR
locations += (vector)llList2String(words,0);
descriptions += llList2String(words,1);
llGetNotecardLine(notecard,current_noteline);
}
}
}

state wait {
state_entry() { llSetRot(ZERO_ROTATION); } //the "default" state when nothing's going on. touching the pointer in the HUD starts the programs
//touch_start(integer total) { llInstantMessage(llGetOwner(),(string)(llGetRegionCorner() + llGetPos())); }
touch_start(integer total) { state ready; }
}

state ready {
on_rez(integer arg) { llResetScript(); } //not too sure what's going on in these lines
attach(key id) { llResetScript(); }
state_entry() {
current_target++;
listener = llListen(0,"",llGetOwner(),"");
llSetTimerEvent(0.2); //sets the frequency that the pointer will updates it's orentation
PointToTarget();
llInstantMessage(llGetOwner(),passed_text+"NEW TARGET: "+llList2String(descriptions,current_target)); // announces a change in waypoints.

}
timer() {
PointToTarget();
float distance = llVecDist(llGetRegionCorner() + llGetPos(),llList2Vector(locations,current_target)); //defines the distance to the waypoint
if (distance < 10) { state next; }// if you get within 10m of the waypoint it will load up the next waypoint.
}
listen(integer channel, string name, key id, string message) {

}
}

state next {
on_rez(integer arg) { llResetScript(); } //not too sure what all the resetting is for.
attach(key id) { llResetScript(); }
state_entry() {
passed_text = "CHECKPOINT PASSED! "; //announces when you've passeda checkpoint.
if (current_target == llGetListLength(locations) - 1) {
current_target = -1; passed_text = "";
llInstantMessage(llGetOwner(),"Tour complete!");
state wait;
} else {
state ready;
}
}
}