Table of Contents

Shortnote

This is a more in-depth explanation of the wasDialogMenu function that conveniently generates lists for llDialog.

Function

///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasMenuIndex = 0;
list wasDialogMenu(list input, list actions, string direction) {
    integer cut = 11-wasListCountExclude(actions, [""]);
    if(direction == ">" &&  (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
        ++wasMenuIndex;
        jump slice;
    }
    if(direction == "<" && wasMenuIndex-1 >= 0) {
        --wasMenuIndex;
        jump slice;
    }
@slice;
    integer multiple = wasMenuIndex*cut;
    input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
    input = wasListMerge(input, actions, "");
    return input;
}

Prototype

The wasDialogMenu takes three parameters:

Case Example

Suppose that we have the following list containing items we want to display with llDialog:

list menu = [ "Aspirin", "Premarin", "Nurofen", "Ampicilin", "Azmacort", "Bentyl", "Cefadroxil", "Clinoril", "Desferal", "Etrafon", "Moderil", "Miralax" ];

and suppose we now call:

llDialog(llGetOwner(), "Please choose: ", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], ""), -10);

this will give us a menu:

Clinoril Desferal Etrafon
Azmacort Bentyl Cefadroxil
Premarin Nurofen Ampicilin
⟵ Back Aspirin Next ⟶
Miralax
⟵ Back Moderil Next ⟶

Now:

Why all the trouble?

The llDialog buttons are are arranged in a certain order, so that the buttons supplied by the list menu have their indices mapped to the corresponding boxes:

9 10 11
6 7 8
3 4 5
0 1 2

Now suppose that we want to display something like:

9 10 11
6 7 8
[EAT ME] 4 [DRINK ME]
[BACK] 1 [NEXT]

Where all the numbers in the table may be occupied by menu items and the special buttons [EAT ME], [DRINK ME], [BACK] and [NEXT] have to always be displayed and always in the positions illustrated by the table.

To do that using the wasDialogMenu function, we call it with:

wasDialogMenu(menu, ["[BACK]", "", "[NEXT]", "[EAT ME]", "", "[DRINK ME]"], "")

and the function takes care of all the rest and returns a menu list that can be fed to llDialog.

Demo

This is a demonstration of the script below based on the previous case-example.

Example Script

endless_menu.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
list menu = [ "Aspirin", "Premarin", "Nurofen", "Ampicilin", "Azmacort", "Bentyl", "Cefadroxil", "Clinoril", "Desferal", "Etrafon", "Moderil", "Miralax" ];
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasMenuIndex = 0;
list wasDialogMenu(list input, list actions, string direction) {
    integer cut = 11-wasListCountExclude(actions, [""]);
    if(direction == ">" &&  (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
        ++wasMenuIndex;
        jump slice;
    }
    if(direction == "<" && wasMenuIndex-1 >= 0) {
        --wasMenuIndex;
        jump slice;
    }
@slice;
    integer multiple = wasMenuIndex*cut;
    input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
    input = wasListMerge(input, actions, "");
    return input;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasListCountExclude(list input, list exclude) {
    if(llGetListLength(input) == 0) return 0;
    if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) 
        return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
    return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasListMerge(list l, list m, string merge) {
    if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return [];
    string a = llList2String(m, 0);
    if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge);
    return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge);
}
 
 
default
{
    touch_start(integer num) {
        llListen(-10, "", llGetOwner(), "");
        llDialog(llGetOwner(), "Please choose: ", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶", "[EAT ME]", "", "[DRINK ME]"], ""), -10);
    }
    listen(integer channel, string name, key id, string message) {
        if(message == "⟵ Back") {
            llDialog(id, "Please browse the available items:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶", "[EAT ME]", "", "[DRINK ME]"], "<"), -10);
            return;
        }
        if(message == "Next ⟶") {
            llDialog(id, "Please browse the available items:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶", "[EAT ME]", "", "[DRINK ME]"], ">"), -10);
            return;
        }
        llSay(0, "You take the \"" + message + "\" out of your backpack and use it.");
    }
}