llDialog(key id, string message, list buttons, integer chat_channel)

Shows the user specified by id a popup dialog box (in the upper right corner of their viewer window) containing message and buttons (and an “Ignore” button). Selecting any of the buttons will cause the avatar to say the text of that button on channel chat_channel.

Even though the chat will originate with the user’s name and key, the chat position will be centered at the object calling llDialog. This ensures the object will be always within listening range of the answer.

Using DEBUG_CHANNEL as the chat_channel will cause avatar to say the button name on the public channel, rather than on the debug channel as one might expect.
Actually, it does go on the debug channel, it’s just that when agents chat on the debug channel, clients see it as though it was public chat. LSL objects see it on DEBUG_CHANNEL

Limits to message:

  • message must be less than 512 characters and may not be empty, though it can contain a single space which will give the appearance of an empty message. If message is empty, the object will say “llDialog: must supply a message”.
  • If message is greater than 511 characters, the object will say “llDialog: message too long, must be less than 512 characters” and the dialog box will not appear.
  • Newline “\n” and tab “\t” escape sequences are valid for formatting the message. Messages with more than 8 lines (including the result of text wrap) will cause a vertical scrollbar to be displayed inside the dialog. There isn’t a way to change the actual size of the dialog box.

Limits to buttons:

  • buttons must be a list of strings; other types are not accepted. Attempting to pass a list containing other types will result in the object saying “llDialog: button list must contain only strings”.
  • buttons must have 12 or fewer entries and can be empty. An empty buttons will simply show the message with an “OK” button.
  • Supplying a space (” “) for an item in buttons will result in an empty button. Clicking the button will still cause the client to say ” “.
  • Empty strings (““) will cause the the object will say “llDialog: all buttons must have label strings” and will not display the dialog box.
  • Entries in buttons cannot be longer than 24 characters. Attempting to pass llDialog a list with entries longer than 24 characters will result in the object saying the message “llDialog:Button Labels can not have more than 24 characters.”, and then fail to show the dialog box.
  • While actual button width is fixed (three buttons to a line), the amount of text that will fit on a button is limited and varies with character width. (“O” is wider than “i”, for example.) If the button label is too long to be viewed, it will be cut off and “…” will be appended. However, the chat output will still contain the full string. “When it cuts off for me it does not put ‘…’. it just cuts. As of August 01, 2008” – Tomithe Aeon
  • Note that regardless of letters involved, the number of characters that can be displayed on a button is never anywhere near 24. More like 8.

If the user selects “Ignore”, the script will not receive an answer, so implement a timeout (recommended) or allow the dialog to be restartable from anywhere.

Notes

  • llDialog will only work if the user identified by id is in the same region or if they have been to that region and left but have not yet logged out.
  • This function delays the script for 1 second.
  • Buttons are drawn left to right, bottom to top. Supplying the list ["1","2","3","4","5"] to buttons will result in “4”, “5”, a space, and on the following line, “1”, “2”, “3”. (see code below for a fix)
  • As of SL 1.8.2(9), the system automatically prepends the string “<Object Owner Name>’s <Object Name>:\n\n” to message before it is displayed.

Examples:

// when touched, present a dialog with four color choices

integer CHANNEL = 42; // dialog channel
list MENU_MAIN = ["Sit", "Stand", "Fly", "Cheat", "Options..."]; // the main menu
list MENU_OPTIONS = ["Cherry", "Blueberry", "Vinegar", "Slime", "Chips", "Salad", "...Back"]; // a submenu

default {
    state_entry() {
        llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users)
    }
    
    touch_start(integer total_number) 
    {
        llDialog(llDetectedKey(0), "What do you want to do?", MENU_MAIN, CHANNEL); // present dialog on click
    }
    
    listen(integer channel, string name, key id, string message) 
    {
        if (llListFindList(MENU_MAIN + MENU_OPTIONS, [message]) != -1)  // verify dialog choice
        {
            llSay(0, name + " picked the option '" + message + "'."); // output the answer
            if (message == "Options...") 
                llDialog(id, "Pick an option!", MENU_OPTIONS, CHANNEL); // present submenu on request
            else if (message == "...Back") 
                llDialog(id, "What do you want to do?", MENU_MAIN, CHANNEL); // present main menu on request to go back
            // here you have the name and key of the user and can easily verify if they have the permission to use that option or not
            else if (message == "Sit") 
                llSay(0, "This is where stuff would happen if this wasn't just an example");
        } else 
            llSay(0, name + " picked invalid option '" + llToLower(message) + "'."); // not a valid dialog choice
    }
}

 

default //Paste this script into an object
{
    touch_start(integer x) //Touch the object
    {
        llDialog(llDetectedKey(0) , "Text" , ["1" , "2" , "3"] , 0); //Select a number, chats it over channel zero.
    }
}

Useful Function:

//Compact function to put buttons in "correct" human-readable order ~ Redux
list order_buttons(list buttons)
{
    return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4) + llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10);
}

//Function that puts buttons in "correct" human-readable order without relying on intelligent higher order list functions ~ Redux
//my bad; fixed 11/25/07
list order_buttons(list buttons)
{
        integer offset;
        list fixt;
        while((offset = llGetListLength(buttons)))
        {
            fixt += llList2List(buttons, offset = -3 * (offset > 3), -1);
            buttons = llDeleteSubList(buttons, offset, -1);
        }
        return fixt;
}

// Loop that puts buttons in "correct" human-readable order, no matter the length of the list.
// Designed to work with "<<" and ">>" buttons, allowing easy browsing of 'virtual' dialog pages. ~ Trullo Oh
for (i=0;i<llGetListLength(BUTTON);i+=3) { BUTTON = llListInsertList(llDeleteSubList(BUTTON, -3, -1), llList2List(BUTTON, -3, -1), i); }

Q & A

Q: What is the equivalent range of llDialog (whisper, say, shout, regionsay)?

A: Responding to the dialog will work as if the object were to use llSay(channel,message), where ‘channel’ is the channel specified by llDialog and ‘message’ is the text that was on the button chosen. This means the range is a 20-meter radius centered on the object.

 

Q: Is there a way to extend (or narrow) the range?

A: Not directly. You could use the listen event trigger a llShout or llRegionSay when it hears a dialog choice, but it doesn’t appear to be possible to narrow the range unless you do something equivalent to an if/else and llVecDist.

 

Q: Do objects receiving messages from the dialog require a certain command or event specific to dialogs, or is it just the standard llListen command and listen event?

A: The button text is said on the channel specified, and can be heard through a standard listen event set to that specific channel. In other words, no, nothing fancy has to be done. It’s just a normal listen event.