Simple Piggy Bank

From Second Life Wiki
Jump to: navigation, search

Purpose

The purpose of this script it to demonstrate how to use llTransferLindenDollars and transaction_result. It builds upon knowing how to request permissions, give user feedback and global variables.

History

This example evolved out an example for the now deprecated function llGiveMoney (the difference between these two functions is that llGiveMoney does not trigger transaction_result). Earlier versions of this post-llGiveMoney example can be found in the history of llTransferLindenDollars.

Code

/*
* A simple piggy bank, anyone can pay in money and anyone can click it to get money out.
*
* TO DO:
*  - handle different errors differently based upon CSV output
*
* original by Strife Onizuka
*
* modified by Kireji Haiku:
*  - because weird things happen in LSL when using more than one state
*  - one should say thanks when being payed
*  - added 0 L$ payment when bank is empty, to show failed payment notifications
*  - added target UUID and L$ amount into transaction history, too
*
* Note from Traven Sachs (VWR-28201):
* In testing this script using an account with no funds - it has been noted that when the INSUFFICIENT FUNDS
* error occurs on Transaction Results that the Display of L$ on the account attempting to transfer funds will
* read as -1 on some viewers, even if the account has funds less than the transaction amount available to it.
* (i.e. if account has 7L and attempts to pay 10L the viewer display will read -1 L until the next L$ transaction
* occurs that is actually valid.  Don't know if this is a viewer glitch or back end glitch but felt it should
* be mentioned.)
*/
 
integer hasBeenGrantedDebitPerms;
 
integer amountGivenAwayOnClick;
integer totalLindenDollarsInBank;
 
list listOfTransactionRecords;
 
update_floattext()
{
    string floattext = "I have no L$ to give away :(";
 
    if (amountGivenAwayOnClick <= totalLindenDollarsInBank
        && hasBeenGrantedDebitPerms)
    {
        floattext = "I have L$ "+ (string)totalLindenDollarsInBank + " to give away!";
    }
 
    llSetText(floattext, <1.0, 1.0, 1.0>, (float)TRUE);
}
 
default
{
    on_rez(integer start_param)
    {
        llResetScript();
    }
 
 
    changed(integer change)
    {
        if (change & CHANGED_OWNER)
            llResetScript();
    }
 
    state_entry()
    {
        // how much money to give away each time?
 
        amountGivenAwayOnClick = 10;
 
        // how much money do we initially "have" in the bank?
 
        totalLindenDollarsInBank = 50;
 
        update_floattext();
 
        // request permissions to give away money, otherwise this won't work
 
        key owner = llGetOwner();
        llRequestPermissions(owner, PERMISSION_DEBIT);
    }
 
    touch_start(integer num_detected)
    {
        // if the script has been granted debit permissions
        if (hasBeenGrantedDebitPerms)
        {
            key id = llDetectedKey(0);
 
            // if we have at least as much money in the bank as we would be giving away
            if (amountGivenAwayOnClick <= totalLindenDollarsInBank)
            {
                // we add the transaction ID, the target avatar UUID and the L$ amount to a list
                listOfTransactionRecords += [llTransferLindenDollars(id, amountGivenAwayOnClick), id, amountGivenAwayOnClick];
 
                // we take the money from the bank
                totalLindenDollarsInBank -= amountGivenAwayOnClick;
            }
            else
            {
                // will not work, cause paying 0 L$!
                // will send a "failed payment" notification!
                // only for DEMO purposes, usually you should do something like:
                // llSay(PUBLIC_CHANNEL, "Sorry, no money in the bank!");
                // instead !!!
 
                listOfTransactionRecords += [llTransferLindenDollars(id, 0), id, 0];
            }
        }
 
        update_floattext();
    }
 
    money(key id, integer amount)
    {
        // someone payed the bank!
 
        totalLindenDollarsInBank += amount;
 
        // be nice, say thanks
        llInstantMessage(id, "Thanks a bunch!");
 
        update_floattext();
    }
 
    transaction_result(key id, integer success, string data)
    {
        integer index = llListFindList(listOfTransactionRecords, [id]);
 
        //if the ID was found in our list
        if (~index)
        {
            // if payment failed, give notice
            if (!success)
            {
                key targetUUID = llList2Key(listOfTransactionRecords, index + 1);
                integer amountNotPayed = llList2Integer(listOfTransactionRecords, index + 2);
 
                llSay(PUBLIC_CHANNEL, "\n \nSorry, somehow the transaction has failed!"
                    + "\ntransaction ID: " + (string)id
                    + "\ntarget UUID: " + (string)targetUUID
                    + "\namount not payed: " + (string)amountNotPayed
                    + "\nfailure reason: " + data);
 
                // if the amount that wasn't payed is more than 0 L$, put the money back into the bank
                if (amountNotPayed)
                    totalLindenDollarsInBank += amountNotPayed;
            }
 
            // remove the entry again [transaction ID, target UUID, L$ amount]
            listOfTransactionRecords = llDeleteSubList(listOfTransactionRecords, index, index + 2);
        }
 
        // total amount could have changed again...
        update_floattext();
    }
 
    run_time_permissions (integer perm)
    {
        // when owner granted debit perms, enable piggy bank functionality
        if(perm & PERMISSION_DEBIT)
            hasBeenGrantedDebitPerms = TRUE;
 
        update_floattext();
    }
}