Table of Contents

Used a Unix time-stamp converter from Void Singer.

Introduction

This is a simple dispenser vendor script we created for Raphael Debs in Second Life. The requirements were to create a primitive that will dispense a random item from the inventory when a certain amount of money is paid into the primitive. After that, the script should remove the item from inventory and update the overhead text, indicating the remaining quantities of items.

I also went the extra mile and made the script keep track of buyers. You may click the vendor primitive in order to get a list of buyers, as well as the time and date that they bought an item from the dispenser.

Setup

integer PRICE = 0;

to a value above 0.

The script will then ask for permissions to debit money and the vendor should be functional.

Notes

  1. If you want to add items to the vendor, open the primitive's contents and add the objects. After that, reset the script.
  2. Hacks: If you want to change the displayed text, simply look at the strings in the code below and change them to something that suits your needs. For example, you could change:
 llSetText("Available items: " + (string)llGetListLength(items), <1,1,1>, 1);

to

 llSetText("Remaining items: " + (string)llGetListLength(items), <1,1,1>, 1);

So that the text displayed above the vendor contains Remaining items instead of Available items. The same applies to all strings in the script.

Code

dispenser_vendor.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.        //
///////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////
//                   CONFIGURATION                      //
//////////////////////////////////////////////////////////
 
// This represents the value of one item in the 
// dispenser. Please set this to some sensible non-zero
// value or the script will not proceed.
integer PRICE = 10;
 
///////////////////////////////////////////////////////////////////////////
//                          END CONFIGURATION                            //
///////////////////////////////////////////////////////////////////////////
 
/////////////////////////////////////////////////////////////////////////////
// The following is an import function from Void Singer. The original URL: //
// http://wiki.secondlife.com/wiki/Stamp2UnixInt and                       //
/////////////////////////////////////////////////////////////////////////////
/*//--                       Anti-License Text                         --//*/
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/
 
list uUnix2StampLst( integer vIntDat ){
    if (vIntDat / 2145916800){
        vIntDat = 2145916800 * (1 | vIntDat >> 31);
    }
    integer vIntYrs = 1970 + ((((vIntDat %= 126230400) >> 31) + vIntDat / 126230400) << 2);
    vIntDat -= 126230400 * (vIntDat >> 31);
    integer vIntDys = vIntDat / 86400;
    list vLstRtn = [vIntDat % 86400 / 3600, vIntDat % 3600 / 60, vIntDat % 60];
 
    if (789 == vIntDys){
        vIntYrs += 2;
        vIntDat = 2;
        vIntDys = 29;
    }else{
        vIntYrs += (vIntDys -= (vIntDys > 789)) / 365;
        vIntDys %= 365;
        vIntDys += vIntDat = 1;
        integer vIntTmp;
        while (vIntDys > (vIntTmp = (30 | (vIntDat & 1) ^ (vIntDat > 7)) - ((vIntDat == 2) << 1))){
            ++vIntDat;
            vIntDys -= vIntTmp;
        }
    }
    return [vIntYrs, vIntDat, vIntDys] + vLstRtn;
}
/////////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//                              INTERNALS                                //
///////////////////////////////////////////////////////////////////////////
 
list items = [];
list buyers = [];
 
default
{
    state_entry()
    {
        if(!PRICE) {
            llOwnerSay("The price is set to 0, please edit the script and set a price in the configuration section.");
            return;
        }
 
        integer itra;
        for(itra=0, items = []; itra<llGetInventoryNumber(INVENTORY_OBJECT); ++itra) {
            items += llGetInventoryName(INVENTORY_OBJECT, itra);
        }
 
        if(llGetListLength(items))
            llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
    }
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_DEBIT) {
            llSetText("Available items: " + (string)llGetListLength(items), <1,1,1>, 1);
            state vend;
        }
    }
}
 
state vend
{
    state_entry() {
        llSetPayPrice(PRICE, (list)PRICE);
    }
 
    touch_start(integer num) {
        if(llDetectedKey(0) != llGetOwner()) return;
        integer itra;
        llOwnerSay("======    BUYERS ======");
        for(itra=0; itra<llGetListLength(buyers); itra+=2) {
            list stm = uUnix2StampLst(llList2Integer(buyers, itra+1));
            llOwnerSay(llList2String(buyers,itra) + " @ " + llDumpList2String(llList2List(stm, 0, 2), "-") + " " + llDumpList2String(llList2List(stm, 3, 5), ":"));
        }
        llOwnerSay("======    BUYERS ======");
    }
 
    money(key id, integer amount) {
        if(amount != PRICE) {
            llInstantMessage(id, "Sorry, L$" + (string)amount + " is not the correct price for an item. The correct price is L$" + (string)PRICE);
            llGiveMoney(id, amount);
            return;
        }
        integer itra = (integer)llFrand(llGetListLength(items));
        string item = llList2String(items, itra);
        items = llDeleteSubList((items = []) + items, itra, itra);
        llGiveInventory(id, item);
        buyers += llKey2Name(id);
        buyers += llGetUnixTime();
        for(itra=0; itra<llGetInventoryNumber(INVENTORY_OBJECT); ++itra) {
            if(llGetInventoryName(INVENTORY_OBJECT, itra) == item) {
                llRemoveInventory(item);
                jump done;
            }
        }
@done;
        llSetText("Available items: " + (string)llGetListLength(items), <1,1,1>, 1);
    }
}