Jump to content

Multiple Menu llDialog in one script?


Raena Parx
 Share

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

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

Recommended Posts

Is it possible to have more than one llDialog menus in the same script?  I'm trying to get an answer from one menu dialog on touch, then automatically open a second menu dialog for a second answer.  What the script does afterward depends on the combination of the two answers.

I've been racking my head trying to make this work.  But as soon as I add the 2nd "listen" command, the script gives a syntax error.  So, I commented it out so the script could be saved.  But consequently, it's not bringing up the second menu.  The script is below.  Any help is appreciated.  :)

Quote

//TEST two menus in one script

integer CHANNEL1 = 42; // dialog MENU channel
integer CHANNEL2 = 43; // dialog MENU channel

integer ListenHandle1;    // Identity of the listener associated with the dialog
integer ListenHandle2;    // Identity of the listener associated with the dialog

integer answer1;
integer answer2;

string MenuDialog1 = "Please choose a button";
list MenuButtons1 = ["[one]", "[two]"]; // the main menu

string MenuDialog2 = "Please choose a button";
list MenuButtons2 = ["[three]", "[four]"]; // the main menu


//-----FIRST MENU TEST-----
default
{
    state_entry()
    {
       ListenHandle1=llListen(CHANNEL1, "", NULL_KEY, ""); // listen enabler CH1 // Sets channel for listing to menu
       ListenHandle2=llListen(CHANNEL2, "", NULL_KEY, ""); // listen enabler CH2 // Sets channel for listing to menu.       
      
    } //end state_entry
    
    touch_start(integer total_number)
    {

        llDialog(llDetectedKey(0),"\n "+MenuDialog1, MenuButtons1, CHANNEL1); // present first dialog on touch

    } //end touch_start

    
     listen(integer CHANNEL1, string nameM, key idM, string answer1)  //listens first time
     {
        
            if (llListFindList(MenuButtons1, [answer1]) != -1)  // verify dialog choice was selected
            {

            llOwnerSay ("Your first answer is : "+ (string)answer1);
        
            } //end if ListFindList

  //   } //end of listen would go here - but moved to end of script so script can continue

//-----SECOND MENU TEST-----
            llListenRemove(ListenHandle1);   // Stop listening to CH1
       
            llDialog(llDetectedKey(0),MenuDialog2, MenuButtons2, CHANNEL2); // present 2nd dialog automatically
            llListen(CHANNEL2, "", NULL_KEY, ""); // second listener enabler // Sets channel for listing to menu.        

    //The line below was //disabled - othewise script would not save, and therefore 2nd menu wont work
    //listen(integer CHANNEL2, string nameM, key idM, string answer2)      //listens 2nd time

    {
      if (llListFindList(MenuButtons2, [answer2]) != -1)  // verify dialog choice was selected
       {
            llOwnerSay ("Your second answer is : "+ (string)answer2);


        } //end if ListFindList
    }  //end of 2nd listen
 

 } //end of first listen

} //end default
 

 

Link to comment
Share on other sites

Every listener fires the same listen() event.

Instead of trying to make more listen events, you just separate them by channel in the same event, like so

listen(integer channel, ...) {
  if(channel == CHANNEL1) {
    // do CHANNEL1 things
  } else if(channel == CHANNEL2) {
    // do CHANNEL2 things
  }
}

 

Edited by Frionil Fang
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Frionil Fang said:

Every listener fires the same listen() event.

Instead of trying to make more listen events, you just separate them by channel in the same event, like so

listen(integer channel, ...) {
  if(channel == CHANNEL1) {
    // do CHANNEL1 things
  } else if(channel == CHANNEL2) {
    // do CHANNEL2 things
  }
}

 

I forgot about this general solution, thanks! I had to lookup llDialog() to see that yep, it says what channel to use.

I haven't worked with dialogs for years, because once you're done..you're done, and I never needed multiple dialogs!

ETA: Guess I used some kind of "state flag" to remember why I was waiting for a dialog response.  In retrospect, using different channels seems a lot simpler.

Edited by Love Zhaoying
  • Haha 1
Link to comment
Share on other sites

Thank you so much Frionil. That looks like a great solution for the listen command. But I will need to call it twice as the menu dialog comes up tiwce.  I'm hoping I can put in a function, then call it more than once - after each menu dialog?

Will play with it some more.  Thank you for the suggestion!   :)

 

 

Link to comment
Share on other sites

So I found an example on the LSL Wiki of using two listening channels:

LlListen - Second Life Wiki

I'm using the LSLEditor to get feedback on the code.  The way the script is written it works perfectly.   But if I try to move the listening sequence of code into a function, it gives these errors:
} expected,  and  Type or namespace definition, or end-of-file expected.

Without putting the listener into a function, I wont be able to call it up twice after each menu dialog.

Any idea why this is giving these errors?

Here is the modified code, just moving the listening sequence into a function:

Quote

//  Opens two listen handles upon touch_start and
//  stops listening whenever something heard passes either filter

integer listenHandle_a;
integer listenHandle_b;

remove_listen_handles()
{
    llListenRemove(listenHandle_a);
    llListenRemove(listenHandle_b);
}

GetAnswer(){
    listen(integer channel, string name, key id, string message)
    {
        if (channel == 5)
            llSay(0, name + " said: '/5 " + message + "'");

        if (channel == 6)
            llSay(0, name + " said: '/6 " + message + "'");

        remove_listen_handles();
    }

}

default
{
    touch_start(integer num_detected)
    {
        key    id   = llDetectedKey(0);
        string name = llDetectedName(0);

        listenHandle_a = llListen(5, "", id, "");
        listenHandle_b = llListen(6, "", NULL_KEY, "");

        llSay(0, "Listening now to '" + name + "' on channel 5.");
          llSay(0, "Listening now to anybody/anything on channel 6.");
        GetAnswer();
    }

}

 

Link to comment
Share on other sites

14 minutes ago, Raena Parx said:

Here is the modified code, just moving the listening sequence into a function:

You can't have event handlers in functions, it doesn't work that way.

integer gListenMode;
string responseA;
string responseB;
integer gHandleListen;
inteegr gChan = -17;

default
{   state_entry()
    {   gHandleListen = llListen(gChan,"","","");
        llListenControl(gHandleListen,FALSE);
    }
    timer()
    {   llSetTimerEvent(0.0);
        llSay(0,"Timed out. Please respond faster.");
        llListenControl(gHandleListen,FALSE);
    }
    touch_start(integer n)
    {   llTextbox(llDetectedKey(0),"Please type response A:",gChan);
        gListenMode=0;
        llListenControl(gHandleListen,TRUE);
        llSetTimerEvent(60.0);
    }
    listen(integer chan, string name, key ID, string text)
    {   if(0==gListenMode)
        {   responseA = text;
            llTextbox(ID,"Please type response B:",gChan);
            gListenMode=1;
            llSetTimerEvent(60.0);
        }else if(1==gListenMode)
        {   responseB = text;
            // Do something intelligent with the responses here:
            llSay(0,"\nReponse A: "+responseA+"\nResponseB: "+responseB);
            // clean up listener:
            llListenControl(gHandleListen,FALSE);
            llSetTimerEvent(0.0);
        }
    }
}
// UNTESTED!

Seems more in line with what you're after?

Edited by Quistess Alpha
Link to comment
Share on other sites

2 hours ago, Raena Parx said:

Thank you so much Frionil. That looks like a great solution for the listen command. But I will need to call it twice as the menu dialog comes up tiwce.  I'm hoping I can put in a function, then call it more than once - after each menu dialog?

You can call llDialog again in the listen event, after you're done processing the first menu. 🙂 The second menu will then be handled in a separately-triggered event.

Here's a complete example of Frionil's suggestion:

default
{
    state_entry()
    {
        // Listen on multiple channels:
        llListen(1, "", "", "");
        llListen(2, "", "", "");

        // Open first menu:
        llDialog(llGetOwner(), "Menu 1", ["one", "two"], 1);
    }

    listen(integer channel, string name, key id, string message)
    {
        if (channel == 1) // First menu
        {
            llOwnerSay("your first answer is " + message);

            // Open next menu right after:
            llDialog(llGetOwner(), "Menu 2", ["three", "four"], 2);
        }
        else if (channel == 2) // Second menu
        {
            llOwnerSay("your second answer is " + message);
        }
    }
}

 

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

Thank you so much, both of you! 

Quistess, I was unable to get that code working, but I really appreciate the effort.

Wulfie, it seems that's exactly what I needed.  I didn't think to stretch out the "if" segment to include the second dialog box after the "listen" command. I can definitely make that work! 

Thank you sooooooooooooooo much!!!!

 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 533 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...