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.
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
Settings you can change
7Edit these at the top of the script. Everything works on the defaults · change them only when you need to.
// =====================================================================
// 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.