Tip Jar API

The tip jars offer a link_message API in case you want to customize or extend their functionality.

Within the link_message event of a script you can react to the following messages:

Message Description integer num string str key id
LOG_IN_REQUESTED Sent when the user clicks the "Log In" button in the menu. 31004 The UUID of the agent requesting the log in
LOG_OUT_REQUESTED Sent when the user clicks the "Log Out" button in the menu. 31005 The UUID of the agent requesting the log out
LOG_IN Sent when a log in or log out was approved and the user is actually logged in/out. 30007 The UUID of the agent logged in, or NULL_KEY on log outs
GOAL_PERCENTAGE_UPDATED Sent if the tip jar is set to be a goal tip jar, and the percentage of the goal reached was updated. 32001 The total amount tipped to this tip jar The goal amount

Using the LOG_IN event, you could, e.g., create a tip jar that follows the logged in person around and returns to a default place when the user logs out.
See below for an example script.

Using the GOAL_PERCENTAGE_UPDATED event, you could create a donation thermometer tip jar. You would calculate the percentage with
integer percentage = ((integer) str) * 100) / ((integer) ((string) id));

Examples

Following Tip Jar

vector OFFSET_FROM_AVATAR_CENTER = <0, 0, 1.5>;

vector g_vecHomePosition;


moveTo(vector vecTarget)
{
    integer i = 0;
    for ( ; i < 10; ++i)
    {
        vector vecBefore = llGetPos();
        llSetPos(vecTarget);
        vector vecAfter = llGetPos();

        if (llVecDist(vecAfter, vecTarget) < 0.01 || vecBefore == vecAfter)
            return;
    }
}

default
{    
    state_entry()
    {
        llSetStatus(STATUS_PHYSICS, FALSE);
    }
    
    on_rez(integer nStartParam)
    {
        llResetScript();
    }

    link_message(integer nSenderNum, integer nNum, string strMsg, key keyUUID)
    {
        if (nNum == 30007)
        {
            if (keyUUID)
            {
                // an agent logged in
                g_vecHomePosition = llGetPos();
                llSensorRepeat("", keyUUID, AGENT, 20, PI, 1);
            }
            else
            {
                // the agent logged out
                llSensorRemove();
                moveTo(g_vecHomePosition);
            }
        }
    }
    
    sensor(integer nNum)
    {
        moveTo(llDetectedPos(0) + OFFSET_FROM_AVATAR_CENTER);
    }
    
    no_sensor()
    {
        // move to the home position if the logged in user has left
        llSensorRemove();
        moveTo(g_vecHomePosition);
    }
}            
        

Stripping Tip Jar

The following script is an example of how you can turn a tip jar into a stripping tip jar. It will strip you when a tip threshold has been reached, and if no more tips are added, will start re-dressing you again after a specific amount of time.

The tip jar plugin script only sends the stripping and dressing commands. For the stripping to work, you will need to attach an additional device, such as Wardrobe's StripMe (which is available to Wardrobe Premium users), or the (CTS) StripMe device.

///////////////////////////////////////////////////////////
// CONFIGURATION

// Set this to TRUE if the script is used in a Xash tip jar.
// Set to FALSE if used in a standalone tip jar. In this case
// it is assumed that the tips will always go to the owner,
// i.e., the owner of the tip jar will be stripped.
integer IS_XASH_TIPJAR = TRUE;

// The amount of tips that needs to be given before the next layer
// of clothes are stripped from the person logged into the tip jar
integer TIPS_TO_STRIP_NEXT_LAYER = 200;

// The number of seconds before a layer of clothing is put on again
integer REDRESS_TIMEMOUT_IN_SECONDS = 600;

// The message that is shown in local chat when stripping occurs.
// The display name of the logged in person will be prepended to the mesage.
string STRIP_ANNOUNCEMENT = "is getting naked! Keep the tips coming if you want to see more skin!";

// An optional UUID of a sound that will be played when stripping occurs.
string STRIP_SOUND_UUID = "";


///////////////////////////////////////////////////////////
// IMPLEMENTATION

key g_keyLoggedInAgent = NULL_KEY;
integer g_nTipsCollected = 0;
integer g_nPreviousStripAmount = 0;
integer g_nNumLayersToStrip = 0;
integer g_bCanStripMore = TRUE;
integer g_bCanDressMore = FALSE;
integer g_bIsStripping = FALSE;


strip()
{
    integer nTimeout = REDRESS_TIMEMOUT_IN_SECONDS;

    if (g_nNumLayersToStrip > 0)
    {
        if (g_bCanStripMore)
        {
            g_bIsStripping = TRUE;
            llRegionSay(-5928148, (string) g_keyLoggedInAgent + "|strip");
        }

        --g_nNumLayersToStrip;
        if (g_nNumLayersToStrip > 0)
            nTimeout = 10;
    }

    llSetTimerEvent(nTimeout);
}

dress()
{
    integer nTimeout = 0;

    if (g_bCanDressMore)
    {
        llRegionSay(-5928148, (string) g_keyLoggedInAgent + "|dress");
        nTimeout = REDRESS_TIMEMOUT_IN_SECONDS;
    }

    llSetTimerEvent(nTimeout);
}

reset()
{
    g_nTipsCollected = 0;
    g_nPreviousStripAmount = 0;
    g_nNumLayersToStrip = 0;
    g_bCanStripMore = TRUE;
    g_bCanDressMore = FALSE;
    g_bIsStripping = FALSE;
}

default
{    
    state_entry()
    {
        // if not a Xash tip jar, assume the tips always go
        // to the owner and the owner is always logged in
        if (!IS_XASH_TIPJAR)
            g_keyLoggedInAgent = llGetOwner();

        reset();
        llListen(-5928148, "", NULL_KEY, "");
    }
    
    on_rez(integer nStartParam)
    {
        llResetScript();
    }

    listen(integer nChannel, string strName, key keyUUID, string strMessage)
    {   
        if (strMessage == "fully-dressed")
            g_bCanDressMore = FALSE;
        if (strMessage == "fully-undressed" || strMessage == "naked")
            g_bCanStripMore = FALSE;

        if (strMessage == "OK" && g_bIsStripping)
        {
            g_bCanDressMore = TRUE;

            if (STRIP_ANNOUNCEMENT)
                llSay(0, "💋👙 " + llGetDisplayName(g_keyLoggedInAgent) + " " + STRIP_ANNOUNCEMENT + " 👙💋");

            if (STRIP_SOUND_UUID)
                llPlaySound(STRIP_SOUND_UUID, 1);
        }

        g_bIsStripping = FALSE;
    }    

    link_message(integer nSenderNum, integer nNum, string strMsg, key keyUUID)
    {
        if (nNum == 30007)
        {
            g_keyLoggedInAgent = keyUUID;
            if (keyUUID)
                reset();
        }
    }

    money(key keyUUID, integer nAmount)
    {
        g_nTipsCollected += nAmount;

        g_nNumLayersToStrip += (g_nTipsCollected - g_nPreviousStripAmount) / TIPS_TO_STRIP_NEXT_LAYER;
        g_nPreviousStripAmount += g_nNumLayersToStrip * TIPS_TO_STRIP_NEXT_LAYER;

        if (g_nNumLayersToStrip > 0)
            strip();
    }

    timer()
    {
        if (g_nNumLayersToStrip > 0)
            strip();
        else
            dress();
    }
}