Jump to content

Having trouble understanding llSetTimerEvent


arisaie
 Share

You are about to reply to a thread that has been inactive for 741 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

So Im working on a dialog texture change script but having a hard time understand llSetTimerEvent function.

This is my script so far. I am under an assumption that llSetTimerEvent should prevent llDialog from firing after a certain period of time. Or is it so that the llSetTimerEvent works but it still returns a command in chat even after 5 seconds (which I set for now)? It still says Texture on Channel 0 after 5 seconds if I click Texture in llDialog. Is it because I have it set wrong or because it should work like that but the llListen stops listening after 5 seconds pass?

I want it to stop listening after 60 seconds in the final version, set it to 5 just to test it.

 

string mainMenuDialog = "\nMain Menu\nWhich settings would you like to access?\nClick \"Close\" to close the menu.";
list mainMenuButtons = ["Texture", "Animation", "Close"];
string textureMenuDialog = "\nTexture Menu\nSelect which texture you would like to apply.";

integer dialogChannel;
integer dialogHandle;

main_menu( key inputKey, string inputString, list inputList)
{
    //CHANGE CHANNEL!!!
    dialogChannel = 0;
    dialogHandle = llListen(dialogChannel, "", inputKey, "");
    llDialog(inputKey, inputString, inputList, dialogChannel);
}

close_menu()
{
    llSetTimerEvent(0.0);// you can use 0 as well to save memory
    llListenRemove(dialogHandle);
}

default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

    touch_start(integer total_number)
    {
        close_menu();
        key id = llDetectedKey(0);
        if (id == llGetOwner());
            {
                main_menu(id, mainMenuDialog, mainMenuButtons);
                llSetTimerEvent(5.0);
                close_menu();
    }
}
    timer()
    {
        close_menu();
    }
}

 

Link to comment
Share on other sites

You can't "disable" an active dialog. But, you can remove the related listener; effectively, you don't care if the user responds or not after the timeout. 

One way a lot of people code the dialog timer is to also whisper something like, "timed out waiting for a response" so the user knows they took too long. 

You will need a listen event that uses the listen handle, if you want to process the dialog response. I wouldn't call your close_menu() function in touch_start(). Just call that if timeout, or after you get a response in the listen energy. 
 

You would normally save the key value returned by the llListen() call, and check for that key in the listen event. The event won't fire after you remove the listener with that key value.

Link to comment
Share on other sites

You could replace the active dialog with a new one that just says something like "Menu timeout" and doesn't have a listener associated with a throwaway channel specified in the llDialog function call.

While some viewers can enable multiple dialogs from the same object the default setting is for new dialogs to replace any existing dialogs that originate from the same object.

And yes, llDialog works like that. It returns the button label clicked by the user as if the user has chatted it on the specified channel. Channel 0 is the public chat channel that everyone hears: it's usual to use a non-zero channel with llDialog so that the command doesn't appear in everyone's chat windows.

Note that in your example you call close_menu() immediately after opening the dialog and setting the timer, so there'll never be a chance for a listen event to hear the button command. You only need to close the listener and disable the timer in both the timer event itself and in the listen event when a button command message is received.

Link to comment
Share on other sites

1 hour ago, KT Kingsley said:

While some viewers can enable multiple dialogs from the same object the default setting is for new dialogs to replace any existing dialogs that originate from the same object.

Some viewers/configurations, do it by both object and channel, so to be on the safer side, I'd recommend using the same channel for a dialog session to a selected avatar when reasonable.

Link to comment
Share on other sites

as has been mentioned already you are removing the listener as soon as you create it

you mostly got it right tho. So i just tidy up an example for you
 

touch_start(integer total_number)
{
   if (llDetectedOwner(0)) // owner touched me
   {
      main_menu(id, mainMenuDialog, mainMenuButtons);
      
      // start the timer in main_menu as the last line
   }
}

listen (..., string text)
{
   close_menu();  // we have the button value in 'text' so we can close main_menu

   ... do something with button 'text' ...
}

timer()
{
   close_menu();
}

 

  • Like 1
Link to comment
Share on other sites

The reason why I called close_menu (llListenRemove) at the start of touch_start is because it was listed on the llDialog wiki. This is there -  "Ensure any outstanding listener is removed before creating a new one"

 touch_start(integer total_number)
    {
        key id = llDetectedKey(0);
        // Ensure any outstanding listener is removed before creating a new one
        close_menu();
        open_menu(id, mainMenuDialog, mainMenuButtons);
    }

I put the llSetTimerEvent(5.0) at the end of touch start and llOwnerSay("Dialog timeout"); in timer() below close_menu().

After I press the button and wait for the "Dialog timeout" message..the dialog no longer brings any submenu (which I added) or doesnt change the texture anymore.

So I guess it works...?

Thanks everyone.

Edited by arisaie
Link to comment
Share on other sites

If the channel number is static, I often use llListenControl() instead of creating a new listen:

integer gChan;
integer gHandleListen;

do_menu(key ID)
{   llListenControl(gHandleListen,TRUE);
    llDialog(ID,"Text",[],gChan);
    llSetTimerEvent(30.0);
}
default
{  state_entry()
   {   gHandleListen = llListen(gChan=(integer)llFrand(1000000)-2000000,"","","");
       llListenControl(gHandleListen,FALSE);
   }
   touch_start(integer n)
   {   do_menu(llDetectedKey(0));
   }
   timer()
   {  llSetTimerEvent(0); // use timer event as a delay rather than repeat.
      llListenControl(gHandleListen,FALSE);
   }
   // listen . . .
}

 

  • Like 1
Link to comment
Share on other sites

On 5/31/2022 at 7:28 AM, Quistess Alpha said:

If the channel number is static, I often use llListenControl() instead of creating a new listen:

 

yes agree

is more efficient to open and close a listener than it is to create and destroy a new one every time for the same use

Link to comment
Share on other sites

1 hour ago, Love Zhaoying said:

Does this mean old dialog responses after the timeout, when you'd call llListenControl(), would still be there later? 

It means that if a listen event is queued and you call llListenRemove() or llListenControl() to remove/deactivate the handle, the listen event will still execute afterwards.

This basically happens when a user responds via dialog during the scope where the timeout protocol is being handled, but before the actual functions get called.

It is a race condition, mostly, but not as uncommon as you'd think.

Edited by Lucia Nightfire
  • Thanks 1
Link to comment
Share on other sites

5 minutes ago, Lucia Nightfire said:

It means that if a listen event is queued and you call llListenRemove() or llListenControl() to remove/deactivate the handle, the listen event will still execute afterwards.

This basically happens when a user responds via dialog during the scope where the timeout protocol is being handled, but before the actual functions get called.

It is a race condition, mostly, but not as uncommon as you'd think.

Got it, that's what I meant in asking. 

Link to comment
Share on other sites

On 5/31/2022 at 7:07 AM, arisaie said:

The reason why I called close_menu (llListenRemove) at the start of touch_start is because it was listed on the llDialog wiki. This is there -  "Ensure any outstanding listener is removed before creating a new one"

sometimes the wiki examples don't fully explain the flow of the event model

two flow examples

1) wait for touch
2) touch
3) close listener
   open listener
   show dialog
   wait for dialog button
4) listen event
   - process button response
5) goto 1)

in this flow the listener is always open, while waiting for touch
 
the code flow should be

1) wait for touch
2) touch
3) open the listener
   show dialog
   wait for dialog button
4) listen event
    - close listener
    - process response
5) goto 1)

the issue with the second flow is when the person doesn't click the dialog button, the listener remains open

so somebody previous invented the listener timeout

1) wait for touch
2) touch
3) open the listener
   show dialog
   start timer
   wait for dialog button
4) listen event
    - stop timer
    - close listener
    - process response
    goto 1)
5) timer event
    - stop timer
    - close listener
    goto 1)
 

 

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 741 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...