Menu Dialog All and Owner problem
|
|
Kay Douglas
Registered User
Join date: 20 Feb 2007
Posts: 41
|
05-19-2008 13:00
Hello, my problem it's a script menu. When I click Test 1 or Test 2 the script is not executed and I do not receive the notecard or the object. I'm the owner of this object. From: someone key owner; key user; integer user_state; integer listening; integer delay = 60; integer channel = -12345678; list owner_options; list all_options; default{ touch_start(integer total_number){ user = llDetectedKey(0); if (user == llGetOwner()) user_state = 2; else user_state = 0; if (user_state == 2) all_options = ["Test All 1","Test All 2","Owner"]; else all_options = ["Test All 1","Test All 2"]; if (user_state == 2) owner_options = ["Test 1","Test 2"]; listening = llListen(channel, "", NULL_KEY, ""  ; llDialog(llDetectedKey(0), "Choose option", all_options, channel); llSetTimerEvent(delay); } listen(integer channel, string name, key id, string message){ if (message == "Test All 1"  { llSay(0,"Test All 1"  ; } else if (message == "Test All 2"  { llSay(0,"Test All 2"  ; } else if (message == "Owner"  { llDialog(id, "Choose option",owner_options, channel); } else if (message == "Test 1"  { llGiveInventory(id, llGetInventoryName(INVENTORY_NOTECARD, 0)); } else if (message == "Test 2"  { llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0)); } llSetTimerEvent(0.0); llListenRemove(listening); } timer(){ llSetTimerEvent(0.0); llListenRemove(listening); } } Thanks for you help 
|
|
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
|
05-19-2008 13:08
Well, like that, it shouldn't even compile - delay should be a float, not an integer.
_____________________
http://ordinalmalaprop.com/forum/ - visit Ordinal's Scripting Colloquium for scripting discussion with actual working BBCode!
http://ordinalmalaprop.com/engine/ - An Engine Fit For My Proceeding, my Aethernet Journal
http://www.flickr.com/groups/slgriefbuild/ - Second Life Griefbuild Digest, pictures of horrible ad griefing and land spam, and the naming of names
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 13:12
1. you're reusing "channel" in your listen. bad form, but not breaking anything. listen(integer channel, string name, key id, string message)
2. your REAL problem, is that your command during "if message == "owner""... creates a new lldialog, but almost immdeiately afterwards, it closes the listen (at the end of the if's)... so it's not LISTENING anymore.
3. Other critiques.. the key "owner" isn't being used that I can see. User_state seems to only be 0 or 2.. any reason why this couldn't be changed to a True/False test with a more intuitive name like "toucherIsOwner"? as a tool for debugging, it's often useful to cast "messages" to lowercase using llToLower. this allows you to always test against a single case situation in your listen/logic engine, while allowing you to "get fancy" with your dialog buttons. you retest for "if (user_state == 2)" twice in your touch event. {} brackets would allow you to gang more than one command into a single if condition result.
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kay Douglas
Registered User
Join date: 20 Feb 2007
Posts: 41
|
05-19-2008 13:20
From: someone key owner; key user; integer user_state; integer listening; float delay = 60; integer channel = -12345678; list owner_options; list all_options; default{ touch_start(integer total_number){ user = llDetectedKey(0); if (user == llGetOwner()) user_state = 2; else user_state = 0; if (user_state == 2) all_options = ["Test All 1","Test All 2","Owner"]; else all_options = ["Test All 1","Test All 2"]; if (user_state == 2) owner_options = ["Test 1","Test 2"]; listening = llListen(channel, "", NULL_KEY, ""  ; llDialog(llDetectedKey(0), "Choose option", all_options, channel); llSetTimerEvent(delay); } listen(integer channel, string name, key id, string message){ if (message == "Test All 1"  { llSay(0,"Test All 1"  ; } else if (message == "Test All 2"  { llSay(0,"Test All 2"  ; } else if (message == "Owner"  { llDialog(id, "Choose option",owner_options, channel); } else if (message == "Test 1"  { llGiveInventory(id, llGetInventoryName(INVENTORY_NOTECARD, 0)); } else if (message == "Test 2"  { llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0)); } llSetTimerEvent(delay); } timer(){ llSetTimerEvent(0.0); llListenRemove(listening); } } The script it's ok now, but it's correct ?
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 13:24
From: Kay Douglas The script it's ok now, but it's correct ? If it compiles, that's the only ACTUAL criteria for whether a script is "correct". (the rules published in the wikis are mostly based on experimentation, not officially documented rules, and even then, there are a lot of different ways to do things in LSL) That doesn't mean it will do what you want, or that it will do it in the most efficient method possible, or that it will even DO anything at all. The question is.. is it working the way you want it to? I would have built the script differently.. and ordinal would have built the script differently from me. In fact, I can think of 5 scripters right now, and even if each of our scripts acted the same to the end user, each of them would come up with a different script.
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kay Douglas
Registered User
Join date: 20 Feb 2007
Posts: 41
|
05-19-2008 13:31
I search to create a good script and what is best way ?
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 13:53
From: Kay Douglas I search to create a good script and what is best way ? What is the "Best" way? I can't tell you that. As I say, each person would approach such a script differently. Here is.. more or less, how I would write it. I'm sure it could be more efficient... though I am learning to dump dynamic button lists, to free up memory. integer toucherIsOwner; integer handle; float delay = 60; integer menuChan; list buttons;
giveMenuMain(key toucher) { llListenRemove(handle); if (toucher == llGetOwner()) toucherIsOwner = TRUE; else toucherIsOwner = FALSE; buttons = (buttons = []) + buttons + ["Test 1", "Test 2"]; if (toucherIsOwner) buttons = (buttons = []) + buttons + "Owner >>"; menuChan = (llFloor(llFrand(4000)) + 4000) * -1; handle = llListen(menuChan, "", toucher, ""); llDialog(toucher, "Choose option", buttons, menuChan); buttons = []; llSetTimerEvent(delay); }
giveMenuOwner(key toucher) { llListenRemove(handle); buttons = (buttons = []) + buttons + ["<< Back", "Test 3", "Test 4"]; menuChan = (llFloor(llFrand(4000)) + 4000) * -1; handle = llListen(menuChan, "", toucher, ""); llDialog(toucher, "Choose option", buttons, menuChan); buttons = []; llSetTimerEvent(delay); }
giveInv(key id, string type) { if(type == "notecard") llGiveInventory(id, llGetInventoryName(INVENTORY_NOTECARD, 0)); else if (type == "object") llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0)); }
default {
touch_start(integer total_number) { giveMenuMain(llDetectedKey(0)); }
listen(integer channel, string name, key id, string message) { llListenRemove(handle); message = llToLower(message); if (message == "test 1") llSay(0,"Test 1"); else if (message == "test 2") llSay(0,"Test 2"); else if (message == "owner >>") giveMenuOwner(id); else if (message == "<< back") giveMenuMain(id); else if (message == "test 3") giveInv(id, "notecard"); else if (message == "test 4") giveInv(id, "object"); }
timer() { llSay(0, "sorry, menu timed out"); llListenRemove(handle); llSetTimerEvent(0.0); } }
Though I would probably add some handling for "what to dio if NO notecards or objects were found.
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kay Douglas
Registered User
Join date: 20 Feb 2007
Posts: 41
|
05-19-2008 14:11
Why used 2 random channel menuChan = (llFloor(llFrand(4000)) + 4000) * -1; for the owner and all ? Thanks for the best way 
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 14:22
From: Kay Douglas Why used 2 random channel menuChan = (llFloor(llFrand(4000)) + 4000) * -1; for the owner and all ? Thanks for the best way  I could have made a single function for generating the listen... and I often do.. but I'm tired, and frankly it works either way. As to why a random channel? it's more secure. The channel is random.. ish.. a number between -4000 and -8000. It makes it a lot harder to accidentally find something on the same channel. Easy to pick channels (1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 22, 33, 69, 13, 99, 666, 12345, 1701, etc) are often used by OTHER people as well. The goal is to avoid the chance of your listen accidentally hearing some other object, and getting confused. My listens are also filtered for the toucher's key... so not only must "something" speak on -4000 through -8000 during that crucial 30 second period.. but it MUST be the toucher who speaks on that channel.. and since avatars can only speak on negative channels by clicking dialog buttons, it's a fairly unlikely condition where another script will deliver a dialog that hits that 1:4000 chance of hitting the right channel... and happens to say something that the script expects to hear. In fact, I would argue that the chance is so slim, as to be practically impossible. By tucking the "open listen" command into the functions, I don't have to shoehorn it into the logic engine of the listen. While it WOULD have been possible to create a single "giveMenu" function that could have given EITHER the owner menu, main menu, or main + owner menu... I felt that breaking it down into 1 menu per function, with a conditional button, made more sense to my way of thinking. (and this is how I create most of my dynamic dialogs "in real life". and now, I'm going to bed. I'll leave it to others to help, if you have any other questions.
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kay Douglas
Registered User
Join date: 20 Feb 2007
Posts: 41
|
05-19-2008 14:35
Yes of course, thank you very much 
|
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
05-19-2008 14:42
I'm fond of this method of choosing a random channel: integer randomNegativeChannel() { return 0x80000000 | (((integer)llFrand(1<<15)) << 16) | (integer)llFrand(1<<16); }
This function uses llFrand() twice since "llFrand can only ever return 24 random bits" ( http://www.lslwiki.net/lslwiki/wakka.php?wakka=llFrand).
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
I'll give it a whirl...
05-19-2008 14:52
For me, the key thing is to not have llDialog scattered all over your code. I'd keep the llListen and llDialog in their own function. Here's my effort: integer mnuChannel; integer mnuHandle; integer delay = 60;
dialogShow(key mnuUser, string mnuTitle, list mnuOptions) { llListenRemove(mnuHandle); mnuChannel = ((integer)llFrand(900000) + 100000) * -1; mnuHandle = llListen(mnuChannel, "", mnuUser, ""); llDialog(mnuUser, mnuTitle, mnuOptions, mnuChannel); llSetTimerEvent(delay); }
default { touch_start(integer total_number) { key user = llDetectedKey(0);
if (user == llGetOwner()) dialogShow(user, "Choose Option", ["Test All 1","Test All 2","Owner"]); else dialogShow(user, "Choose Option", ["Test All 1","Test All 2"]); }
listen(integer channel, string name, key id, string message) { llSetTimerEvent(0.0); llListenRemove(mnuHandle);
if (message == "Test All 1") llSay(0,"Test All 1"); else if (message == "Test All 2") llSay(0,"Test All 2"); else if (message == "Owner") dialogShow(id, "Choose Option", ["Test 1","Test 2"]); else if (message == "Test 1") llGiveInventory(id, llGetInventoryName(INVENTORY_NOTECARD, 0)); else if (message == "Test 2") llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0)); }
timer() { llSetTimerEvent(0.0); llListenRemove(mnuHandle); } }
..this is not The Correct Solution. It's a solution but I hope you can see that it has removed a lot of the clutter, especially from the touch_start event handler. And, in particular, the listen and dialog handling are no longer woven into the main body of the code.
|
|
Kidd Krasner
Registered User
Join date: 1 Jan 2007
Posts: 1,938
|
05-19-2008 15:18
From: Winter Ventura If it compiles, that's the only ACTUAL criteria for whether a script is "correct" As an SQA engineer, this raises my hackles. I think what you're really getting at is that there are usually several different good ways to write a script, and that being well-written can include some subjectivity. A script, or any program, is correct if it satisfies all the requirements, both explicit and implicit. Maintainability is often an implicit requirement.
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 15:27
From: Kidd Krasner As an SQA engineer, this raises my hackles. I think what you're really getting at is that there are usually several different good ways to write a script, and that being well-written can include some subjectivity.
A script, or any program, is correct if it satisfies all the requirements, both explicit and implicit. Maintainability is often an implicit requirement. As an SQA engineer, you work with a scripting language that has official documentation.. not people estimating what the built in delays appear to be, and writing clever workarounds to what appears to be intended behaviours, but doesn't work as expected. That's LSL. KLUDGE. Don't take my words out of context like that. From: someone If it compiles, that's the only ACTUAL criteria for whether a script is "correct". (the rules published in the wikis are mostly based on experimentation, not officially documented rules, and even then, there are a lot of different ways to do things in LSL) That doesn't mean it will do what you want, or that it will do it in the most efficient method possible, or that it will even DO anything at all. There is no status of "CORRECT LSL"... there is functional, and nonfunctional, efficient, and inefficient, slow, and hard on the server. There is such a thing as "well formed" (using a float when a float is called for, not reusing variable names from events on the global level)... but "correct" implies that there is only ONE way. And in LSL, there is more often than not, dozens of ways to approach the same result. And as I was reminded again recently... "your code is working perfectly.. it's just not doing what you want it to do". But the only binary status in LSL that APPROACHES "correct/incorrect" is "does compile, does not compile". If you want correct/incorrect, study math. If you want right and wrong, study religion. If you want a headache and an ulcer, study LSL.
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kidd Krasner
Registered User
Join date: 1 Jan 2007
Posts: 1,938
|
05-19-2008 15:43
From: Winter Ventura ... My listens are also filtered for the toucher's key... so not only must "something" speak on -4000 through -8000 during that crucial 30 second period.. but it MUST be the toucher who speaks on that channel.. and since avatars can only speak on negative channels by clicking dialog buttons, it's a fairly unlikely condition where another script will deliver a dialog that hits that 1:4000 chance of hitting the right channel... and happens to say something that the script expects to hear. In fact, I would argue that the chance is so slim, as to be practically impossible.
Since channels can be any integer, it's actually less than 1 in 4x 10^9. I can't think of any reason for limiting the numbers to the -8000 to -4000 range. Also, depending on the specific circumstances, it may or may not be worth generating a new channel number for each menu, as opposed to generating it once on script start (or perhaps on rez).
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
05-19-2008 15:46
From: Kidd Krasner Since channels can be any integer, it's actually less than 1 in 4x 10^9. I can't think of any reason for limiting the numbers to the -8000 to -4000 range. Also, depending on the specific circumstances, it may or may not be worth generating a new channel number for each menu, as opposed to generating it once on script start (or perhaps on rez). I wrote the script the way I would have done. I had my reasons. Continued bickering does not serve the OP
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Kidd Krasner
Registered User
Join date: 1 Jan 2007
Posts: 1,938
|
05-19-2008 17:09
From: Winter Ventura As an SQA engineer, you work with a scripting language that has official documentation.. not people estimating what the built in delays appear to be, and writing clever workarounds to what appears to be intended behaviours, but doesn't work as expected. That's LSL. KLUDGE.
Hehe, that's a matter of opinion. Ever read the ECMAScript spec, or try to get JavaScript working the same under multiple versions of multiple browsers? From: someone There is no status of "CORRECT LSL"... there is functional, and nonfunctional, efficient, and inefficient, slow, and hard on the server. There is such a thing as "well formed" (using a float when a float is called for, not reusing variable names from events on the global level)... but "correct" implies that there is only ONE way. And in LSL, there is more often than not, dozens of ways to approach the same result.
I'm not sure where you're getting the implication that correct implies just one way. It's not true in general (e.g., both 'gray' and 'grey' are correct spellings), and it's certainly not true when used to describe programs. A program is correct when it satisfies its requirements, as I said previously. There's nothing about that to suggest there's only one way to do it. The language doesn't really matter either. We could be talking about an LSL/HTTP/PHP system. Being correct and being syntactically and semantically valid are different concepts.
|
|
Kornscope Komachi
Transitional human
Join date: 30 Aug 2006
Posts: 1,041
|
05-19-2008 19:45
This thread has been a good scripting lesson, for me anyway.
_____________________
SCOPE Homes, Bangu -----------------------------------------------------------------
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
05-20-2008 03:37
From: Kidd Krasner Being correct and being syntactically and semantically valid are different concepts. And trying to show what you know as opposed to lending anything at all valid to the conversations such as examples as others have posted , plus stating your "qualifications" is rude and arrogant. SQA engineer does not mean a thing around here. Helpful comments, snippets or full examples do help.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime. From: someone I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
|