// ===================================================================== // 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(); } }