-->

FoxSan's 3D Tools and LSL Script Repository

Tons of LSL scripts, examples and 3D tools, free for all. There are currently 207 scripts and articles in this database.

Donation Script

// CARP Donation box script. Written by Angel Fluffy, with credit to :
// Keknehv Psaltery, jean cook, ama omega, nada epoch, YadNi Monde
// for their work on the "DONATION box" script upon which it was based.
 
string imtext = "I'm the __________ Donation Box! Please right click and pay me to donate, as this supports the __________ project and helps keep the place open for you!";
// this is the text sent to someone who clicks on the prim containing this script and who isn't the owner.
 
// first line of hover text above box (always constant)
string floaty = "__________ Donation Box\n";
 
// when total donated this month is less than monthlyneeded, display whatfunding_1 as the funding target,
// when it is more, display whatfunding_2. This allows you to show your donors when you have switched
// from funding your essential running costs to funding expansion.
string whatfunding_1 = "Funding : __________ \n";
string whatfunding_2 = "Funding : __________ \n"; 
 
// name of the current month
// we *could* get this automatically, but changing the month automatically isn't as easy as it seems.
// This is a change I might make in a future version.
string thismonth = "October"; 
 
// How much are we trying to raise per month?
// The script displays a countdown in SETTEXT above the prim its in, counting down until this target is reached.
// After this target is reached, the countdown disappears, being replaced with a tally.
// The goal of this is to encourage people to donate by setting a clear goal they feel they can help achieve by donating.
integer monthlyneeded = 30000;
 
// These two variables define the starting numbers for how much has been donated across all time, and how much this month.
// These starting numbers will have the donations the script recieves in between each reset/save added to it,
// and the result displayed in float text over the top of the script.
// The first time you start accepting donations, you should set both of the numbers below to zero.
// When saving this script, you (the object owner) should touch the donation box object,
// which will then tell you how much has been donated in total and how much has been donated this month.
// Entering this information here before saving will allow you to preserve the 'state' of the script across edits/restarts.
integer totaldonated = 0;
integer monthdonated = 0;
 
// these settings are like the above, but save the 'last donor' information. You can set them to "" and 0 to clear saved info.
string lastdonor = "Taffy Tinlegs";
integer lastdonated = 0;
 
// this interval defines how long we wait between each reminder to donate broadcast to SAY (range=20m)
integer timer_interval = 3600;
 
// these settings determine what the 'default' donation amounts are.
// the buttons are the 'fast pay' buttons, the 'payfield' is the default amount in the text box.
list paybuttons = [50,200,400,800];
integer payfield = 100;
 
// these variables should be left undefined.
string owner;
string otext;
integer mpercent;
 
integer updatemath() {
        float mpercentfloat = ((monthdonated * 100) / monthlyneeded);
        mpercent = (integer)mpercentfloat; 
 
 return 1;
}
 
integer updatetext() {
        otext = floaty;
 
        if (mpercent >= 100) {
            otext += whatfunding_2;
        } else {
            otext += whatfunding_1;
        }
        if (lastdonated > 0) {
            otext += "Last donation : L$" + (string)lastdonated + " by " + lastdonor +"\n";
        }
        if (mpercent >= 100) {
            otext += "We have raised L$"+(string)(monthdonated - monthlyneeded)+" for this, beyond our basic running costs of L$"+(string)monthlyneeded+" for "+thismonth+". \n";
            //otext += "The excess will go towards giving prizes and running special events!";
        } else {
            otext += "Our donors have contributed "+(string)mpercent+"% of our basic running costs ("+(string)monthdonated+"/"+(string)monthlyneeded+") for "+thismonth+".\n";
        }
        llSetText(otext,<1,1,1>,1);
 return 1;
}
default
{
    on_rez( integer sparam )
    {
        llResetScript();
    }
    state_entry()
    {
        updatemath();
        updatetext();
        owner = llKey2Name( llGetOwner() );
        llSetPayPrice(payfield,paybuttons);
        llSetTimerEvent(timer_interval);
        llSay(0,"Script updated. Usually this is caused by the donation box owner updating the script.");
    }
 
    money(key id, integer amount)
    {
        totaldonated += amount;
        monthdonated += amount;
        lastdonor = llKey2Name(id);
        lastdonated = amount;
        updatemath();
        updatetext();
        llInstantMessage(id,"On behalf of everyone who uses this place, thank you for the donation!");
        llSay(0,(string)llKey2Name(id)+" donated L$" + (string)amount + ". Thank you very much for supporting us, it is much appreciated!" );
    }
    touch_start(integer num_detected){
        if (llDetectedKey(0) == llGetOwner()) {
            llOwnerSay("Reporting script status, because you are recognised as the owner of this donation box.");
            llOwnerSay("Current TOTAL donations across all time: L$"+(string)totaldonated);
            llOwnerSay("Current TOTAL donations for this month: L$"+(string)monthdonated);
        }  else {
            llInstantMessage(llDetectedKey(0),imtext);
        }
    }
    timer() {
        integer premainder = 100 - mpercent;
        integer aremainder = monthlyneeded - monthdonated;
        if (mpercent < 100) {
            llSay(0,"We still need to meet the last "+(string)premainder+"% of our basic costs (L$"+(string)aremainder+") this month, to pay for land tier etc. Please consider donating to help us out!");
        }
        llSetTimerEvent(timer_interval);
    }
}

Pay Roll Tool

//Here's a handy little script I wrote up to exchange money with people who are either far away or offline. Since the only other way to pay someone is in person by the pie chart, this can come in very handy. Especially for payroll of employees, hence the name.
 
//The only catch is you need the persons key but this can be acquired several different ways; make them touch a scripted object and log it, use a sensor on them, use a sensor on their in world objects if they're offline, etc. I can post several scripts to get keys if people need.
 
//IM me in game if you'd like a copy of the script without having to cut and paste it.
 
// payroll.ll by Rathe Underthorn "00aa39a8-f6a4-45be-991e-b1e1fca8fe5b"
// say @pay <NICKNAME> <AMOUNT> to pay a user on your payroll list.
 
float fVersion = 1.0;
 
list lsPeople =
[
// ADD PEOPLE HERE AS "NICKNAME", "KEY",
 
"Arthur", "62091005-826d-44cd-ab80-0a6b96915b44", // Arthur Money
"Carrera", "e6b0b6e9-0dee-4e6e-bfb9-c725d0db3f01", // Carrera LeFay
"Darwin", "3e722bd8-028c-713f-e4f7-2e9b680855c8", // Darwin Appleby
"Kaylis", "16f627e1-ab89-4b1f-827f-63bd7bd3a7b9", // Kaylis LeFay
"Rathe", "00aa39a8-f6a4-45be-991e-b1e1fca8fe5b", // Rathe Underthorn
"Si", "117274fd-3902-4a07-b411-09bdc79f0fad", // Si Money
"Yuki", "3e8a2608-661d-ca16-0492-9233c77d3d1c", // Yuki Sunshine
 
// DO NOT REMOVE THIS END ROW
 
"END", "END"
];
 
integer nPublicChannel = 0;
integer nPublicId = 0;
string szTarget = "";
integer nAmount = 0;
key kTarget = NULL_KEY;
 
init_listen()
{
llListenRemove(nPublicId);
nPublicId = llListen(nPublicChannel, "", NULL_KEY, "");
}
 
key target_to_key(string szTarget)
{
integer i;
integer nListSize = llGetListLength(lsPeople) - 2;
 
for (i = 0; i < nListSize; i += 2)
{
if (llToLower(llList2String(lsPeople, i)) == llToLower(szTarget))
{
return llList2Key(lsPeople, i + 1);
}
}
 
return NULL_KEY;
}
 
default
{
state_entry()
{
szTarget = "";
nAmount = 0;
kTarget = NULL_KEY;
init_listen();
}
 
on_rez(integer nStartParam)
{
szTarget = "";
nAmount = 0;
kTarget = NULL_KEY;
init_listen();
}
 
listen(integer nChannel, string szName, key kId, string szMessage)
{
if (nChannel == nPublicChannel)
{
if (kId == llGetOwner())
{
if (llGetSubString(llToLower(szMessage), 0, 4) == "@pay ")
{
integer nCmdLen = llStringLength(szMessage);
string szTokens = llGetSubString(szMessage, 5, nCmdLen);
 
integer nTokenPos = llSubStringIndex(szTokens, " ");
integer nTokenLen = llStringLength(szTokens);
 
szTarget = llGetSubString(szTokens, 0, nTokenPos - 1);
nAmount = (integer)llGetSubString(szTokens, nTokenPos + 1, nTokenLen);
 
kTarget = target_to_key(szTarget);
 
if (kTarget != NULL_KEY)
{
integer nPerm = llGetPermissions();
 
if (!(nPerm & PERMISSION_DEBIT))
{
llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
}
else
{
llWhisper(0, "Paying " + szTarget + " $" + (string)nAmount);
llGiveMoney(kTarget, nAmount);
}
}
}
}
}
}
 
run_time_permissions(integer nPermissions)
{
if (nPermissions) // permission granted
{
if (kTarget != NULL_KEY)
{
llWhisper(0, "Paying " + szTarget + " $" + (string)nAmount);
llGiveMoney(kTarget, nAmount);
}
}
else
{
llWhisper(0, "You denied debit permission, payments will not work, try again...");
}
}
}

Pay To Teleport

//Pay 2 Teleport by Haplo Voss
//Greetings! Thanks be to all that helped me along the way with answers to questions!
//Without further ado... here it is!!
 
//Please pay attention to notes following script!!
 
//-------------------------
 
vector gTargetPos;
integer cost;
string desc;
string hovertext;
key agent;
key gAvatarID=NULL_KEY;
integer gReturnToStartPos=TRUE;
vector gStartPos;
integer paid = 1;
integer access=0;
integer public_access;
integer origin_access;
float elapsed;
key gID;
 
warpPos( vector destpos)
{ //R&D by Keknehv Psaltery, 05/25/2006
//Additions by Strife, Talarus Luan
//and final cleanup by Keknehv Psaltery
integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
if (jumps > 100 )
jumps = 100;
list rules = [ PRIM_POSITION, destpos ];
integer count = 1;
while ( ( count = count << 1 ) < jumps)
rules = (rules=[]) + rules + rules;
llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1, count) );
}
 
default
{
 
dataserver(key query_id, string desc){
list desc_list = llParseString2List(desc, [";"], []);
gTargetPos = (vector)llList2String(desc_list, 0);
cost = (integer)llList2String(desc_list, 1);
hovertext = llList2String(desc_list, 2) + "\n" +
llList2String(desc_list, 3) + "\n" +
llList2String(desc_list, 4) + "\n" +
llList2String(desc_list, 5) + "\n" +
llList2String(desc_list, 6);
public_access = (integer)llList2String(desc_list, 7);
origin_access = public_access;
}
 
money (key id, integer amount){
paid=amount;
 
if (paid < cost && public_access == 0){
llSay(0,"Sorry, but this class costs " + (string)cost + ". Full amount is required before access.");
llGiveMoney(id,paid);
llUnSit(llAvatarOnSitTarget());
}
else if (paid > cost && public_access == 0){
integer refund = paid - cost;
llSay(0,"This class only costs " + (string)cost + "! Refunding you L$" + (string)refund );
llSay(0,"Access Granted!");
llSetSitText("Teleport");
llGiveMoney(id,refund);
gID = id;
public_access = 1;
}
else if (paid != 0 && origin_access == 1){
integer refund = paid;
llSay(0,"This teleporter is public access!");
llSay(0,"Access Granted!");
llSetSitText("Teleport");
llGiveMoney(id,refund);
public_access = 1;
}
else{
llSay(0,"Access Granted!");
llSetSitText("Teleport");
gID = id;
public_access = 1;
 
}
 
}
 
on_rez(integer rez){
llResetScript();
}
 
state_entry(){
llRequestPermissions(llGetOwner(),PERMISSION_DEBIT );
desc = llGetNotecardLine("TPInfo",0);
llSitTarget(<0,0,1>,ZERO_ROTATION);
gStartPos = llGetPos();
}
 
touch_start(integer touched){
llSetSitText("\n");
llSetText(hovertext, <0,1,0>, 1);
if (public_access == 1){llSetSitText("Teleport");}
elapsed = llGetAndResetTime();
}
touch(integer num_detected) {
if (llDetectedKey(0) == llGetOwner()){
elapsed = llGetTime();
if (elapsed > 2.0) {
llOwnerSay("Description has changed - resetting script");
llSetTimerEvent(120);
llResetScript();
}
 
}}
touch_end(integer num_detected)
{}
 
timer()
{
llSetTimerEvent(0.0);
}
 
changed(integer change){
if(change & CHANGED_LINK)
gAvatarID = llAvatarOnSitTarget();
if(public_access == 0){llSetSitText("\n");llUnSit(gAvatarID);}
if(gAvatarID != NULL_KEY & public_access == 1 & gID == gAvatarID) {
warpPos(gTargetPos);
llSleep(.25);
llUnSit(gAvatarID);
llSleep(.25);
 
if (gReturnToStartPos) {
warpPos(gStartPos);
}
if(origin_access == 0){llSetSitText("\n");public_access = 0;}
if(origin_access == 1){llSetSitText("Teleport");}
}
}
}
 
//------------------------------
 
//As you can see in the script, you will need to create a notecard called "TPInfo" (no quotes). It must contain the following information, IN THE FOLLOING ORDER.
 
//<destination vector>;price to charge;text line1;line2;line3;line4;line5;public access switch
 
//EXAMPLE:
 
//<1,2,3>;100;WELCOME!;Right Click And;Pay L$100 to;Teleport to Island!; ; ;0
 
//vector = <1,2,3>
//price = 100
//text =
//WELCOME!
//Right Click And
//Pay L$100 to
//Teleport to Island!

Event Lottery Script

// Event Lottery Script by Ama Omega
//This is a simple script for randomly awarding money to event attendies. Everyone who wishes to enter simply clicks the object the script is on. To find a winner the owner of the object says 'Find Winner'. This can be repeated as often as needed to find as many winners as possible. After a name has 'won' it is removed from the pool. This is a simple script.
 
list names;
integer i;
integer j;
integer count;
string name;
 
integer find(string name)
{
    for (i=0;i<count;i++)
        if (llList2String(names,i) == name)
            return i;
    return -1;
}
 
default
{
    state_entry()
    {
        llListen(0,"",llGetOwner(),"Find Winner");
        count = 0;
    }
 
    touch_start(integer total_number)
    {
        for (j=0;j<total_number;j++)
        {
            if (find(llDetectedName(j)) == -1)
            {
                name = llDetectedName(j);
                names += name;
                llSay(0,name + " has been entered.");
                count++;
            }
        }
    }
 
    listen(integer chan, string name, key id, string mes)
    {
        names = llListRandomize(names,1);
        i = llFloor(llFrand(llGetListLength(names)));
        llWhisper(0,"And the Winner is " + llList2String(names,i) +
            "! There were " + (string)count + " participants.");
        llDeleteSubList(names,i,i);
    }
}

Auto Raffler

//  AUTORAFFLER version 1.1
//  by Neo Rebus
//  Copyright (c) 2004 by Johnson Earls, All Rights Reserved
//  See end of file for license information
//
//  This is an automatic raffling system.  Once started, it will
//  periodically conduct a raffle on its own and give the prize to the
//  winner.  The winner must accept the prize within 15 seconds or the
//  autoraffler will choose a different winner.  (This allows the owner
//  of the object or property to decline accepting a prize)
//
//  SETUP:
//
//  Create an object that fills the volume in which the raffle attendees
//  will be standing.  The object can consist of multiple prims.  Once
//  the autoraffle script is put on the object, it will become phantom.
//  The object should be named something descriptive (as it will say
//  things to the world), and should be transparent since people will be
//  standing inside it.
//
//  Put the autoraffle script into the raffler object, then put the
//  objects to be raffled in.  Everything being raffled must be an
//  *object*, not a texture or landmark or anything.  If you want to
//  raffle other types of things off, put them inside their own object
//  and raffle that object.  If you want to raffle money, make an object
//  named "L$### ..." and the winner will be given ### linden dollars
//  rather than the object itself.
//
//  at this point, the autoraffler accepts voice commands to control it:
//
//    autoraffle reset
//      to reset the script
//    autoraffle list
//      to list the people entered in the raffle
//    autoraffle list winners
//      to list people who have won the raffle since it was reset
//    autoraffle stop
//      to stop an ongoing raffle
//    autoraffle start [ <interval> [ <count> ] ]
//      to start a raffle.  <interval> and <count> are optional.  If
//      interval is not given, it will default to about 30 seconds.
//      If count is not given, it will raffle off all the objects in
//      the autoraffler's inventory.
//
//      example:  autoraffle start 20 5
//        this will start the autoraffler with a raffle every 20 minutes
//        (starting 20 minutes from now), raffling off 5 random prizes.
//
 
integer raffleAcceptTimeout = 15;
 
integer runningRaffleCount = 0;
integer runningRaffleInterval = 0;
 
integer runningRaffleListenerChat = 0;
integer runningRaffleListenerPrivate = 0;
 
list runningRaffleEntrants = [];
list runningRaffleWinners = [];
 
key thisRafflePrize = NULL_KEY;
string thisRafflePrizeName = "";
key thisRaffleWinner = NULL_KEY;
string thisRaffleWinnerAccepted = "";
list thisRaffleEntrants = [];
 
integer PRIVATE_CHAT = 1316110706 ;
 
list remove_from_list(list src, list what)
{
    //  find 'what'
    integer idx = llListFindList(src, what);
    if (idx > -1)
    {
        list pfx;  // the list before 'what'
        list sfx;  // the list after 'what'
        if (idx > 0)
        {
            pfx = llList2List(src, 0, idx - 1);
        } else {
            pfx = [];
        }
        if (idx < llGetListLength(src) - llGetListLength(what))
        {
            sfx = llList2List(src, idx + llGetListLength(what), -1);
        } else {
            sfx = [];
        }
        return pfx + sfx;
    } else {
        return src;
    }
}
 
raffleWinner(key winner)
{
 
    //  if the winner is not NULL_KEY, give them the prize.
    //  if the winner *is* NULL_KEY, give the script owner the prize.
    //  remove the prize from the inventory, decrement the raffle count, and call nextRaffle().
 
    if (winner == NULL_KEY)
    {
        llSay(0, "No one accepted the prize!");
        if (llGetSubString(thisRafflePrizeName, 0, 1) != "L$")
        {
            llGiveInventory(llGetOwner(), thisRafflePrizeName);
        }
    } else {
        if (llGetSubString(thisRafflePrizeName, 0, 1) == "L$")
        {
            llGiveMoney(winner, llList2Integer(llParseString2List(thisRafflePrizeName, [" ", "$"], []), 1));
        } else {
            llGiveInventory(winner, thisRafflePrizeName);
        }
        runningRaffleWinners = runningRaffleWinners + [ winner ];
    }
 
    llRemoveInventory(thisRafflePrizeName);
 
    thisRafflePrize = NULL_KEY;
    thisRafflePrizeName = "";
    thisRaffleWinner = NULL_KEY;
 
    runningRaffleCount -= 1;
 
    nextRaffle();
}
 
nextRaffle()
{
    llSetTimerEvent(0.0); // just in case
 
    //  if the raffle count is 0, announce the end of the raffle and reset running variables.
    if (runningRaffleCount == 0)
    {
 
        runningRaffleInterval = 0;
        thisRafflePrize = NULL_KEY;
        thisRafflePrizeName = "";
        thisRaffleWinner = NULL_KEY;
        thisRaffleWinnerAccepted = "";
        thisRaffleEntrants = [];
        llSay(0, "The raffle is over!  Thank you for attending!");
 
    } else {
 
        //  compute the timer value.  if < 5, set it to 5.
        float timer_value = runningRaffleInterval - llGetTime();
        if (timer_value < 30.0)
        {
            timer_value = 30.0;
        }
        llSetTimerEvent(timer_value);
 
        //  initialize raffle params.
        thisRaffleWinner = NULL_KEY;
        thisRafflePrize = NULL_KEY;
        thisRafflePrizeName = "";
 
        //  announce the raffle.
        if (timer_value < 120)
        {
            llSay(0, "The next raffle is coming up!");
        } else {
            llSay(0, "The next raffle will be in " + (string)(llFloor(timer_value / 60.0)) + " minutes.");
        }
 
    }
}
 
chooseWinner()
{
 
    integer nument = llGetListLength(thisRaffleEntrants);
 
    //  if no valid entrants, call raffleWinner(NULL_KEY) to give item back to owner.
    if (nument == 0)
    {
        raffleWinner(NULL_KEY);
    } else {
 
        //  pick a random person from the entrants.  Announce that they won.
        //  give them a dialog to allow them to decline the prize, and set a
        //  timer for the timeout.
 
        integer winner = llCeil(llFrand(nument)) - 1;
 
        thisRaffleWinner = llList2Key(thisRaffleEntrants, winner);
        llSay(0, "The winner is " + llKey2Name(thisRaffleWinner) + "!");
        llSetTimerEvent(raffleAcceptTimeout);
        llDialog(thisRaffleWinner, "Do you wish to accept the raffle prize " + thisRafflePrizeName + "?", [ "Yes", "No" ], PRIVATE_CHAT);
 
    }
 
}
 
default
{
 
    state_entry()
    {
        // turn off the timer
        llSetTimerEvent(0.0);
 
        // get permission to give money
        llRequestPermissions(llGetOwner(),PERMISSION_DEBIT    );
 
        // reset the running raffle parameters
        runningRaffleCount = 0;
        runningRaffleInterval = 0;
        runningRaffleEntrants = [];
        runningRaffleWinners = [];
 
        thisRafflePrize = NULL_KEY;
        thisRafflePrizeName = "";
        thisRaffleWinner = NULL_KEY;
 
        // turn volume detect off, then back on, to force collision_start events
        llVolumeDetect(FALSE);
        llSleep(0.1);
        llVolumeDetect(TRUE);
 
        // remove listeners and re-add them
        llListenRemove(runningRaffleListenerChat);
        llListenRemove(runningRaffleListenerPrivate);
        runningRaffleListenerChat = llListen(0, "", NULL_KEY, "");
        runningRaffleListenerPrivate = llListen(PRIVATE_CHAT, "", NULL_KEY, "");
    }
 
    on_rez(integer start_code)
    {
        // reset script
        llResetScript();
    }
 
    collision_start(integer total_number)
    {
        integer i;
        for (i=0; i<total_number; i++)
        {
            //  in order to be an avatar, the detected item's key must = the item's owner.
            if (llDetectedKey(i) == llDetectedOwner(i))
            {
                //  check if the detected person is already in Entrants.  if not, add them.
                if (llListFindList(runningRaffleEntrants, [ llDetectedKey(i) ]) == -1)
                {
                    runningRaffleEntrants = runningRaffleEntrants + [ llDetectedKey(i) ];
                }
            }
        }
    }
 
    collision_end(integer total_number)
    {
        integer i;
        for (i=0; i<total_number; i++)
        {
            //  remove the person from Entrants
            runningRaffleEntrants = remove_from_list(runningRaffleEntrants, [ llDetectedKey(i) ]);
        }
    }
 
    listen(integer channel, string name, key id, string msg)
    {
 
        // convert msg to lowercase
        msg = llToLower(msg);
 
        // on chat channel, listen for "autoraffle" commands.
        if ((channel == 0) && (id == llGetOwner()) && (llGetSubString(msg, 0, 10) == "autoraffle "))
        {
 
            if (msg == "autoraffle stop")
            {
 
                //  turn autoraffle off by setting the runningRaffleCount to 0 and calling nextRaffle()
                runningRaffleCount = 0;
                nextRaffle();
 
            } else if (msg == "autoraffle list")
            {
 
                //  generate comma-separated list of entrants with 'and' between last two
                integer i;
                integer num;
                string entrants = "";
                num = llGetListLength(runningRaffleEntrants);
                for (i=0; i<num; i++)
                {
                    string name = llKey2Name(llList2Key(runningRaffleEntrants, i));
                    if (i == 0)
                    {
                        entrants = name;
                    } else if (i == num - 1)
                    {
                        if (i > 1)
                        {
                            entrants = entrants + ",";
                        }
                        entrants = entrants + " and " + name;
                    } else {
                        entrants = entrants + ", " + name;
                    }
                }
                llSay(0, "The current raffle entrants are " + entrants);
 
            } else if (msg == "autoraffle list winners")
            {
 
                //  generate comma-separated list of entrants with 'and' between last two
                integer i;
                integer num;
                string winners = "";
                num = llGetListLength(runningRaffleWinners);
                for (i=0; i<num; i++)
                {
                    string name = llKey2Name(llList2Key(runningRaffleWinners, i));
                    if (i == 0)
                    {
                        winners = name;
                    } else if (i == num - 1)
                    {
                        if (i > 1)
                        {
                            winners = winners + ",";
                        }
                        winners = winners + " and " + name;
                    } else {
                        winners = winners + ", " + name;
                    }
                }
                llSay(0, "The raffle winners so far have been " + winners);
 
            } else if (msg == "autoraffle reset")
            {
 
                //  reset script
                llResetScript();
 
            } else if ((msg == "autoraffle start") ||
                       (llGetSubString(msg, 0, 16) == "autoraffle start "))
            {
 
                // split message into params, set interval and count,
                // and call nextRaffle()
                list params = llParseString2List(msg, [" "], []);
                integer npar = llGetListLength(params);
                if (npar > 2)
                {
                    runningRaffleInterval = llList2Integer(params, 2);
                } else {
                    runningRaffleInterval = 0;
                }
                if (npar > 3)
                {
                    runningRaffleCount = llList2Integer(params, 2);
                } else {
                    runningRaffleCount = llGetInventoryNumber(INVENTORY_OBJECT);
                }
                llResetTime();
                nextRaffle();
 
            }
        }
 
        if ((channel == PRIVATE_CHAT) && (id == thisRaffleWinner))
        {
 
            // on the private chat, set the Accepted string and reset
            // the timer to go off as quickly as possible
            thisRaffleWinnerAccepted = msg;
            llSetTimerEvent(0.1);
 
        }
 
    }
 
    timer()
    {
 
        // unset the timer
        llSetTimerEvent(0.0);
 
        // if we don't have a winner, then we're still selecting one.
        if (thisRaffleWinner == NULL_KEY)
        {
 
            // if we don't have a prize key, then we need to announce it.
            if (thisRafflePrize == NULL_KEY)
            {
                // reset the time so the next raffle is based on this time.
                llResetTime();
 
                // if we don't have any entrants, then skip this raffle attempt
                if (llGetListLength(thisRaffleEntrants) == 0)
                {
 
                    nextRaffle();
 
                } else {
 
                    // if we have no items, let the raffle owner know via IM
                    integer n = llGetInventoryNumber(INVENTORY_OBJECT);
                    if (n == 0)
                    {
 
                        llInstantMessage(llGetOwner(), llGetObjectName() +
                            ": No items left to raffle!");
                        nextRaffle();
 
                    } else {
 
                        n = llCeil(llFrand(n)) - 1;
                        thisRafflePrizeName = llGetInventoryName(INVENTORY_OBJECT, n);
                        thisRafflePrize = llGetInventoryKey(thisRafflePrizeName);
                        llSetTimerEvent(10.0);
                        llSay(0, "Now raffling: " + thisRafflePrizeName);
 
                    }
                }
 
            } else {
 
                // we have a prize key, find a winner.
                thisRaffleEntrants = runningRaffleEntrants;
                chooseWinner();
 
            }
        } else {
 
            //  we have a winner.  therefore they've already been offered
            //  the win dialog.  if they accept, call raffleWinner(); otherwise,
            //  remove them from thisRaffleEntrants and call chooseWinner() again.
            if (thisRaffleWinnerAccepted == "yes")
            {
                raffleWinner(thisRaffleWinner);
            } else {
                llSay(0, llKey2Name(thisRaffleWinner) + " did not accept the raffle prize.");
                thisRaffleEntrants = remove_from_list(thisRaffleEntrants, [ thisRaffleWinner ]);
                chooseWinner();
            }
        }
 
    }
 
}
 
////////////////////////////////////////////////////////////////////////
//
//  Auto-Raffler version 1.0
//  by Neo Rebus
//  Copyright (c) 2004 by Johnson Earls
//  All Rights Reserved
//
//  Permission to Use and Redistribute
//
//  Permission to use and redistribute the Auto-Raffler code, with or
//  without modifications, is granted under the following conditions:
//
//  + All redistributions must include this copyright notice and license.
//  + All redistributions must give credit to the author, by real name
//    (Johnson Earls) and by SL name (Neo Rebus).  If distributed in a
//    modified form, credit must still be given to Neo Rebus (Johnson
//    Earls) as the original author.
//  + All redistributions *should* include the setup information at the
//    beginning of the script.
//
////////////////////////////////////////////////////////////////////////