Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Still learning, but having trouble returning a value

Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
11-30-2008 21:37
I'm having trouble getting my head around how to pass a variable from one state to another cleanly in LSL. I'm working on a script that receives a string of information in chat, does some string manipulation and then needs to get an avatar key from a name that was part of the input string. I am trying to get the key with a call to a new state. ......

CODE

// input some stuff, then ...

list temp = llParseString2List(message, ["="], []);
avname = llStringTrim(llList2String(temp, 0), STRING_TRIM);
string avwords = llStringTrim(llList2String(temp, 1), STRING_TRIM);
llOwnerSay(avname + " : " + avwords + "# " + (string)avkey);

//OK to here. "avkey" is empty so far.

state check_av; // <<< -----here's the call to the new state
llOwnerSay("Avkey = " + (string)avkey); //<<--- This statement doesn't fire. WHY?


The new state looks like this (almost verbatim from w-hat.com's Name2Key) ....

CODE

state check_av
{

state_entry()
{
reqid = llHTTPRequest( URL + "?terse=1&name=" +llEscapeURL(avname), [], "" );
}

http_response(key id, integer status, list meta, string body)
{
if ( id != reqid )
{
return;
}
if ( status == 499 )
{
llOwnerSay("name2key request timed out");
return;
}
else if ( status != 200 )
{
llOwnerSay("the internet exploded!!");
return;
}
else if ( body == "" )
{
avkey = NULL_KEY;
llSay(0,"Sorry, " + avname + "is unknown. Please check spelling.");
return;
}
else
{
avkey = (key) body;
llOwnerSay(avkey); // <<-- This works. I get a real key loaded in avkey.
return;
}
}
}


BTW, both (string)avname and (key)avkey are defined globally.

When I test the script, it tells me a valid key in that last llOwnerSay statement, so I know that the variable avkey is loaded. In my naive mind, I expect the "return" statements to take me right back to the calling state, where I ought to be able to use that newly-loaded value of avkey, but it doesn't. What am I not understanding?:confused:
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
11-30-2008 21:43
Your miss in understanding is how states work. You need to manually call any state-change. I'm not sure what exactly your script is doing with the rest of its code, but you may not want to change states at all - or possibly run your avatar key-check through a separate script with a link-message sent back and forth.

Anyway ... instead of "return" after receiving info, you'll wanna set your script to return to "state default" (or whatever your starting state is).

As a side note - I try to avoid state-changes wherever possible...I find them to be cludgy.
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
11-30-2008 21:49
OK. That sorta makes sense, but if I return from state check_av to state default, I'll end up back at the top of my script. I want to come right back where I left the action. I'm still new enough at LSL that I know the problem is in my understanding of how states work. In any other language I've worked with, I would simply call a subroutine to do the calculation, then return to the statement after the call. That's the wrong way to look at this, but what's the right way?
SuezanneC Baskerville
Forums Rock!
Join date: 22 Dec 2003
Posts: 14,229
11-30-2008 22:22
Would you define a function instead of using a state?
_____________________
-

So long to these forums, the vBulletin forums that used to be at forums.secondlife.com. I will miss them.

I can be found on the web by searching for "SuezanneC Baskerville", or go to

http://www.google.com/profiles/suezanne

-

http://lindenlab.tribe.net/ created on 11/19/03.

Members: Ben, Catherine, Colin, Cory, Dan, Doug, Jim, Philip, Phoenix, Richard,
Robin, and Ryan

-
Nyoko Salome
kittytailmeowmeow
Join date: 18 Jul 2005
Posts: 1,378
11-30-2008 22:58
:0 you're jumping state before the llOwnerSay gets a chance to fire. jumping to another script state is like jumping out of a loop - nothing after that call will go; only what's in the next state that you're calling up.

p.s. oh, that was your original script ;0 not the modded one... sorry trying to 'read' the script instead of going inworld to try it. ;)

states do not return values, period. :\ hafta save any result to a global var, if you want to access the value from another state.

also, there is no 'returning' from a state, but you can jump either forwards or backwards by just calling 'state whichstate' again.
_____________________

Nyoko's Bodyoils @ Nyoko's Wears
http://slurl.com/secondlife/Centaur/126/251/734/
http://home.comcast.net/~nyoko.salome2/nyokosWears/index.html

"i don't spend nearly enough time on the holodeck. i should go there more often and relax." - deanna troi
Kenn Nilsson
AeonVox
Join date: 24 May 2005
Posts: 897
12-01-2008 06:47
Lemme give you a code sample that might help:


SCRIPT #1

CODE

integer KEY_GET = 1;
integer KEY_RETURN = 2;
integer KEY_EMPTY = 4;
integer KEY_ERROR = 8;
string sdetect;

default
{
touch_start(integer num)
{
sdetect = llDetectedName(0);
llMessageLinked(-4,KEY_GET,sdetect,NULL_KEY);
}
link_message(integer sender, integer int, string str, key id)
{
if(int == KEY_RETURN)
{
kdetect = id;
//continue with your code
}
else if(int == KEY_EMPTY)
{
//state unable-to-find-key error
}
else if(int == KEY_ERROR)
{
//state error
}
}
}



SCRIPT #2

CODE

integer KEY_GET = 1;
integer KEY_RETURN = 2;
integer KEY_EMPTY = 4;
integer KEY_ERROR = 8;

string URL = "http://w-hat.com/name2key";

key reqid;

default
{
link_message(integer sender, integer int, string str, key id)
{
if(int == KEY_GET) reqid = llHTTPRequest(URL + "?terse=1&name=" + llEscapeURL(str), [], "");
}
http_response(key id, integer status, list meta, string body)
{
if(id != reqid) return;
if(status == 499) llMessageLinked(-4,KEY_ERROR,"Request Time-Out",NULL_KEY);
else if(status != 200) llMessageLinked(-4,KEY_ERROR,"The internet expoded!", NULL_KEY);
else if((key)body == NULL_KEY) llMessageLinked(-4,KEY_EMPTY,"",NULL_KEY);
else llMessageLinked(-4,KEY_RETURN,"",body);
}
}



You can technically work the whole process in a single script - though I'm not sure what else you're doing with your particular script and how it would need to work through. I figured I'd give you an idea of how I tend to do things.
_____________________
--AeonVox--

Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms chasing ghosts, eating magic pills, and listening to repetitive, addictive, electronic music.
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-01-2008 06:52
From: Nyoko Salome
.... states do not return values, period. :\ hafta save any result to a global var, if you want to access the value from another state.


OK, but the variable avkey IS a global variable, so it should have the newly asssigned value available when I return to state default, right?:confused:

From: someone
also, there is no 'returning' from a state, but you can jump either forwards or backwards by just calling 'state whichstate' again.


Yes, I see that's the problem, but what's the solution? If I say "state default;" then I will leave state check_av and go back to the top of state default. That's not where I want to go. So it seems that if I use this approach, there is no way to get back to the place where I left, right?:(

From: Suezanne Baskerville
Would you define a function instead of using a state?


Now, THAT's a good idea, and it would seem to do what I want, because I CAN return from a user-defined function to the place I called from. Problem is, I'm new enough at LSL coding that I don't understand how to rewrite what I have in state check_av as a function. Any suggestions?

Again, thank you for being patient with me. I'm never afraid of poking at a new challenge, if I can learn from it.
Pedro McMillan
SLOODLE Developer
Join date: 28 Jul 2007
Posts: 231
12-01-2008 07:11
Unfortunately, since your check_av state relies on events (http_response), you can't put that into a function at all. It's not really a problem to fix everything though.

Take everything you need to do after you've got the avatar key, and put it at the end of the "http_response" event in your check_av state (in the bit where you successfully check your avatar key), and then switch back to the default state. That way, everything gets done that you need, and when you go back to the default state, it doesn't matter that you're back at the top of it.
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-01-2008 07:30
@Kenn: Thank you. You were apparently posting your reply as I was writing mine, so we crossed in cyberspace. That's a possibility I hadn't even considered, although I know you mentioned it in your first response last night. I haven't tried linking scripts yet -- another hurdle to leap -- but your guidance may be all I need to give it a try.

@Pedro: Yeah, that's what I figured too. That's why I didn't jump at the idea of writing a function in the first place. I was willing to try it if someone could point the way, though. Your suggestion of repackaging the rest of the stuff in the calling event and putting it in state check_av might be the easiest thing to do -- even easier than Kenn's suggestion. I'll have to re-think the way I do a couple of other things in that event, but that's a good idea.

Thanks. Two good ideas to play with. I really appreciate the help. :D
Nyoko Salome
kittytailmeowmeow
Join date: 18 Jul 2005
Posts: 1,378
12-01-2008 11:34
sorry i didn't entirely grok your script; s'hard to figure it out just by sight-reading ;) yah, things get hairy when you want to function around any lsl function that's state-bound, like a dataserver event... can seem wasteful on global vars sometimes, but not much else to do about it.

states are a bit funky to get used to at first - sometimes it's easier to just have a 'mode' var and leave everything in one state. pros and cons either way... i don't know if this helps understand, but unless instructed to state-jump, or perhaps run something regularly on a timer, the script will simply 'sit idle' in its last state after running whatever state_entry code it's handled. or it waits for a touch_start to process... somehow i remember this messing me up when i first started playing with lsl. ;0

good luck, have fun! :)
_____________________

Nyoko's Bodyoils @ Nyoko's Wears
http://slurl.com/secondlife/Centaur/126/251/734/
http://home.comcast.net/~nyoko.salome2/nyokosWears/index.html

"i don't spend nearly enough time on the holodeck. i should go there more often and relax." - deanna troi
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-01-2008 11:48
Thanks. It does help, Nyoko. I'm finding it easier to translate my flow diagram into a set of states than to think of everything happening in a single state, but I'm still finding myself thinking in linear terms when it comes to the execution of events. That's what led me into the trap of expecting states to behave like subroutines, even though I should know better. After working with a range of languages since Fortran II days, LSL's way of doing things takes a little getting used to.