Bubble Trapper - Launcher

bubble_trapper_launcher.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//                              INTERNALS                                //
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//    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);
}
 
list menu = [];
list keys = [];
 
integer Name2Number(string name) {
    list alph = ["*", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
    integer i = llStringLength(name)-1;
    integer ahash = 0;
    do {
        ahash += llListFindList(alph, (list)llToLower(llGetSubString(name, i, i)));
    } while(--i>-1);
    return ahash;
}
 
default {
 
    state_entry() {
        if(llGetInventoryNumber(INVENTORY_OBJECT) == 0) {
            llSay(DEBUG_CHANNEL, "I don't have an object loaded in my inventory. Please add an object and try again...");
            return;
        }
    }
 
    on_rez(integer param) {
        llResetScript();
    }
 
    touch_start(integer num) {
        if(llDetectedKey(0) != llGetOwner()) return;
        llSensor("", "", AGENT, 64, TWO_PI);
    }
 
    sensor(integer num) {
        menu = [];
        keys = [];
        --num;
        do {
            key av = llDetectedKey(num);
            if(llVecDist(llGetPos(), llDetectedPos(num)) > 64) jump continue;
            menu += llGetSubString(llDetectedName(num), 0, 12);
            keys += av;
@continue;
        } while(--num>-1);
        if(llGetListLength(menu) == 0) {
            llOwnerSay("Sorry, I could not find anybody in range to poof.");
            return;
        }
        integer comChannel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6));
        llListen(comChannel, "", llGetOwner(), "");
        llDialog(llGetOwner(), "Please select an avatar to surround in the bubble from the list below:\n", wasDialogMenu(menu, ["<= Back", "[ MASS ]", "Next =>"], ""), comChannel);
    }
 
    listen(integer channel, string name, key id, string message) {
        if(message == "<= Back") {
            llDialog(id, "Please browse the available avatars:\n", wasDialogMenu(menu, ["<= Back", "[ MASS ]", "Next =>"], "<"), channel);
            return;
        }
        if(message == "Next =>") {
            llDialog(id, "Please browse the available avatars:\n", wasDialogMenu(menu, ["<= Back", "[ MASS ]", "Next =>"], ">"), channel);
            return;
        }
        if(message == "[ MASS ]") state trap;
        menu = (list)message;
        state trap;
    }
}
 
state trap {
    state_entry() {
        integer i = llGetListLength(menu)-1;
        do {
            llRezObject(llGetInventoryName(INVENTORY_OBJECT,0), llGetPos() + <0,0,1>, ZERO_VECTOR, ZERO_ROTATION, Name2Number(llList2String(menu, i)));
        } while(--i>-1);
        state default;
    }
}