skimi3d Grid Log in Visit the grid
All scripts
Hand things out

Giver on Touch

Touch it and it hands over what is inside, and it never accidentally hands over its own script. Can also keep it to one each.

Goes inA box, a sign, or whatever holds the gift
Setup7 to set
Code158 lines
Open toOpen to everyone

What it does

On a touch it gives out its Contents: one thing on its own, or everything at once as a folder named after the object. It leaves the scripts behind, which is the single most common accident with a box like this and not a small one. With ONE_PER_PERSON it remembers who has already had one, and it writes that down only after something has actually gone out, so a person whose gift failed is not locked out of the one they never received.

What you can build with it

The freebie box by the door, a gift at an event, the demo copy beside the thing you are selling, a starter kit at the landing point, a prize, a welcome pack of landmarks. Set ONE_PER_PERSON and it becomes a gift table rather than a tap.

How to use it

1 Rez a box or a sign and drop this script into it.
2 Drop what you are giving away into the same prim's Contents.
3 Change LABEL to say what touching it gets. That floating line is the whole invitation.
4 Check the permissions on what you are giving. Next owner needs copy, or your visitor gets one they cannot keep properly.
5 Touch it yourself and look at what arrives, and where in your inventory it lands.

Settings you can change

7

Edit these at the top of the script. Everything works on the defaults · change them only when you need to.

LABEL Floating words above it so people know what it is. This line is the whole invitation: Touch me says nothing, Touch for a free copy says everything. Touch for a free copy
LABEL_COLOUR The colour of that label. <1.0, 1.0, 1.0>
ONLY_GIVE Give only this one thing, by name. Left empty it gives everything in Contents except the scripts, as one folder. (empty)
THANKS What it says to whoever touched it. Empty says nothing. There you go. Look in your Inventory, in a folder named after me.
ONE_PER_PERSON One each. The names are remembered only while the script runs, so a region restart forgets them. FALSE
ALREADY_HAD_IT What it says to somebody coming back for a second when ONE_PER_PERSON is on. You have had one of these already.
WHO_MAY_TAKE 0 for everyone, 1 for the owner alone, 2 for anyone wearing the same group tag. 0
The code LSL · 158 lines · updated 8 Sep 2026 Download .lsl
// =====================================================================
//  Giver on Touch
//  skimi3d script library
//  https://grid.skimi3d.com/scripts/giver-on-touch
//
//  Touch it and it hands over what is inside: an object, a texture, a
//  landmark, a whole folder of them. The freebie box by the door, the
//  gift at an event, the demo copy beside the thing you are selling.
//
//  It can also remember who has already had one, which is the setting
//  that turns a gift into one gift each.
//
//  Plain LSL.
// =====================================================================


// ---------------------------------------------------------------------
//  Settings
// ---------------------------------------------------------------------

// Floating words above it, so people know what it is. Empty for none.
string LABEL = "Touch for a free copy";
vector LABEL_COLOUR = <1.0, 1.0, 1.0>;

// Give only this one thing, by name. Left empty it gives everything in
// its Contents except the scripts, as one folder.
string ONLY_GIVE = "";

// What it says to whoever touched it. Empty says nothing.
string THANKS = "There you go. Look in your Inventory, in a folder named after me.";

// One each. The names are remembered while the script runs, so a
// region restart forgets them and everyone may have another.
integer ONE_PER_PERSON = FALSE;
string  ALREADY_HAD_IT = "You have had one of these already.";

// Who may take one. 0 = everyone, 1 = only the owner, 2 = same group.
integer WHO_MAY_TAKE = 0;


// ---------------------------------------------------------------------
//  Everything below here is the machinery
// ---------------------------------------------------------------------

list gTaken = [];


integer mayTake(key who)
{
    if (WHO_MAY_TAKE == 1) return who == llGetOwner();
    if (WHO_MAY_TAKE == 2) return llSameGroup(who);
    return TRUE;
}


// Everything in Contents except the scripts.
//
// Handing somebody the script that runs the giver is the single most
// common accident with a box like this, and it is not a small one: it
// gives away work you may not have meant to give away.
list contents()
{
    list out = [];
    integer n = llGetInventoryNumber(INVENTORY_ALL);
    integer i;

    for (i = 0; i < n; ++i)
    {
        string name = llGetInventoryName(INVENTORY_ALL, i);
        if (llGetInventoryType(name) != INVENTORY_SCRIPT) out += [name];
    }

    return out;
}


// TRUE when something really went out, so the thank-you only follows a
// gift and not a failure.
integer give(key who)
{
    if (ONLY_GIVE != "")
    {
        if (llGetInventoryType(ONLY_GIVE) == INVENTORY_NONE)
        {
            llOwnerSay("There is nothing called \"" + ONLY_GIVE + "\" in my Contents.");
            llRegionSayTo(who, 0, "Sorry, there is nothing here to give you just now.");
            return FALSE;
        }

        llGiveInventory(who, ONLY_GIVE);
        return TRUE;
    }

    list stuff = contents();
    integer n = llGetListLength(stuff);

    if (n == 0)
    {
        llOwnerSay("I have nothing to give. Drop something into my Contents.");
        llRegionSayTo(who, 0, "Sorry, there is nothing here to give you just now.");
        return FALSE;
    }

    if (n == 1)
    {
        llGiveInventory(who, llList2String(stuff, 0));
        return TRUE;
    }

    llGiveInventoryList(who, llGetObjectName(), stuff);
    return TRUE;
}


default
{
    state_entry()
    {
        llSetText(LABEL, LABEL_COLOUR, 1.0);
        gTaken = [];
    }

    touch_start(integer total)
    {
        integer i;
        for (i = 0; i < total; ++i)
        {
            key who = llDetectedKey(i);

            if (!mayTake(who))
            {
                llRegionSayTo(who, 0, "This one is not for you, sorry.");
            }
            else if (ONE_PER_PERSON && llListFindList(gTaken, [(string)who]) != -1)
            {
                if (ALREADY_HAD_IT != "") llRegionSayTo(who, 0, ALREADY_HAD_IT);
            }
            else if (give(who))
            {
                // Only written down once something actually went out.
                // Marking somebody as served for a gift that failed
                // would lock them out of the one they never got.
                if (ONE_PER_PERSON) gTaken += [(string)who];
                if (THANKS != "") llRegionSayTo(who, 0, THANKS);
            }
        }
    }

    changed(integer what)
    {
        if (what & CHANGED_INVENTORY) llSetText(LABEL, LABEL_COLOUR, 1.0);
    }

    on_rez(integer start)
    {
        llResetScript();
    }
}

Copy it, make a new script inworld, paste over what is there and save. Nothing here phones home.