Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Another question

Reina Therian
Registered User
Join date: 20 Jun 2004
Posts: 11
08-17-2004 10:48
When an obect is dropped into another object's inventory and the 'changed' event is called, is there any way to know WHO dropped it? I know that when you touch something, you can use llDetectedKey(0). Is there something similar that can be used when a changed event is called?
Jake Cellardoor
CHM builder
Join date: 27 Mar 2003
Posts: 528
08-17-2004 12:47
Unfortunately, no. This feature has been requested several times; maybe we'll get it someday.
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
08-17-2004 12:57
Make the user click the object before they drop something into the contents.
_____________________
C U B E Y · T E R R A
planes · helicopters · blimps · balloons · skydiving · submarines
Available at Abbotts Aerodrome and XstreetSL.com

Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
08-17-2004 13:33
From: someone
Originally posted by Cubey Terra
Make the user click the object before they drop something into the contents.

Problem with that is, how does one know when a person clicks it and *doesnt* drop an object in :)
==Chris
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
08-17-2004 16:21
Pretty simple script, actually. :D

CODE


list oldList;
//To prevent a call off the bat, remember
//to list the objects from the get-go in
//state_entry.

changed(integer change)
//Gah. Where's a CHANGE_INVENTORY command
//when I want one? I'd like to just write
//if(change & CHANGE_INVENTORY), but...
//I'm guessing there's an integer call of some type
//for it. :rolleyes:
list inventory_types = [INVENTORY_BODYPART,INVENTORY_CLOTHING,INVENTORY_LANDMARK,INVENTORY_NOTECARD,INVENTORY_OBJECT,INVENTORY_SCRIPT,INVENTORY_SOUND,INVENTORY_TEXTURE];
integer inventory_count = llGetListLength(inventory_types);
//Now for the annoying part - seeing what inventory
//item is new since LSL likes to split it up by type
//(Although I would hope the lack of type
//would list inventory in no particular order...
//let's play it safe, shall we?
if(inventory_types != oldList)
{
linteger i;
for(i=0;i<llGetListLength(inventory_types,i++)
{//Start the for loop to search current items..
//All this does is search every value in the list
//and return a name for it, then see if the name
//is already in the list. If it's not, we get the owner
//of the item.
if(llListFindList(oldList,(list)llList2String(inventory_types,i) == -1)
{
key iKey = llGetInventoryKey(llList2String(inventory_types,i));
llSay(0,"New item Detected! An item called '" + llList2String(inventory_types,i) + "' was just added by avatar " + llGetOwnerName(iKey));
}
}
}

Now, in theory this would work. However, given how screwy permissions are, it's very possible the contents would automatically flip to the owner of the parent prim and say as much. :rolleyes:

So, if that didn't work, the only way to divine whodunit would be a touch version of the above (not too impressive) or a detector/llVolumeDetect, which is a rather gimped way of doing it. :rolleyes:

If only there were an llGetCreator/llGetCreatorName... though, even that would not solve the problem. :rolleyes:

The only other way one could do it is with specific items. For example, a player adds an item that must have his name on it somewhere (ie. "Hoverbike by Jeffrey Gomez";). Call a sensor. If the avatar is found within a 5m range (to prevent falsifying the information) via llSubStringIndex(objectName, llKey2Name(llDetectedKey(i))), allow the addition - otherwise, remove it.
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
08-17-2004 23:46
From: someone
Originally posted by Jeffrey Gomez
Pretty simple script, actually. :D

CODE


list oldList;
//To prevent a call off the bat, remember
//to list the objects from the get-go in
//state_entry.

changed(integer change)
//Gah. Where's a CHANGE_INVENTORY command
//when I want one? I'd like to just write
//if(change & CHANGE_INVENTORY), but...
//I'm guessing there's an integer call of some type
//for it. :rolleyes:
list inventory_types = [INVENTORY_BODYPART,INVENTORY_CLOTHING,INVENTORY_LANDMARK,INVENTORY_NOTECARD,INVENTORY_OBJECT,INVENTORY_SCRIPT,INVENTORY_SOUND,INVENTORY_TEXTURE];
integer inventory_count = llGetListLength(inventory_types);
//Now for the annoying part - seeing what inventory
//item is new since LSL likes to split it up by type
//(Although I would hope the lack of type
//would list inventory in no particular order...
//let's play it safe, shall we?
if(inventory_types != oldList)
{
linteger i;
for(i=0;i<llGetListLength(inventory_types,i++)
{//Start the for loop to search current items..
//All this does is search every value in the list
//and return a name for it, then see if the name
//is already in the list. If it's not, we get the owner
//of the item.
if(llListFindList(oldList,(list)llList2String(inventory_types,i) == -1)
{
key iKey = llGetInventoryKey(llList2String(inventory_types,i));
llSay(0,"New item Detected! An item called '" + llList2String(inventory_types,i) + "' was just added by avatar " + llGetOwnerName(iKey));
}
}
}

Now, in theory this would work. However, given how screwy permissions are, it's very possible the contents would automatically flip to the owner of the parent prim and say as much. :rolleyes:

So, if that didn't work, the only way to divine whodunit would be a touch version of the above (not too impressive) or a detector/llVolumeDetect, which is a rather gimped way of doing it. :rolleyes:

If only there were an llGetCreator/llGetCreatorName... though, even that would not solve the problem. :rolleyes:

The only other way one could do it is with specific items. For example, a player adds an item that must have his name on it somewhere (ie. "Hoverbike by Jeffrey Gomez";). Call a sensor. If the avatar is found within a 5m range (to prevent falsifying the information) via llSubStringIndex(objectName, llKey2Name(llDetectedKey(i))), allow the addition - otherwise, remove it.


Um... Jeff, no offence but I'm noticing some pretty glaring logic flaws with your code.

1: Items are never added to oldlist; it is initilized to [] and left there.

2: oldList is compared to a list of INVENTORY_* constants. I dont think that was the intention.

The only 100% perfect solution to the "whodunnit" changed-event-problem would be the addition of a new parameter to changed, or the addition of an llGetChanger function.

Here's what I think you meant:

CODE

// List of all inventory types. Necessesary since there is no INVENTORY_ALL constant.
// NOTE: If a new inventory type is added, this list MUST be updated.
list INVENTORY_TYPES = [
INVENTORY_TEXTURE, INVENTORY_SOUND,
INVENTORY_OBJECT, INVENTORY_SCRIPT,
INVENTORY_LANDMARK, INVENTORY_CLOTHING,
INVENTORY_BODYPART, INVENTORY_NOTECARD,
INVENTORY_ANIMATION,INVENTORY_GESTURE];

// List of items in tasks' inventory before the changed event occurs.
list oldItems = [];

default {
changed(integer change) {
// Integer representing all types of inventory changes:
integer INVENTORY_CHANGE = CHANGED_INVENTORY | CHANGED_ALLOWED_DROP;

// If inventory has changed:
if ((change & INVENTORY_CHANGE) == INVENTORY_CHANGE) {
// A list of items added to inventory.
list addedItems = [];
// A list of all items in inventory after the event occurs.
list curItems = [];

// The following code goes through the inventory contained in the prim,
// adding it to addedItems if it was not already in oldItems, adding it to curItems
// reguardless, since curItems will be used to update oldItems with new data about
// the object's inventory.
integer typeIndex;
integer numTypes = llGetListLength(INVENTORY_TYPES);

// For every type:
for (typeIndex = 0; typeIndex < numTypes; typeIndex++) {
integer type = llList2Integer(INVENTORY_TYPES, typeIndex);

integer inventoryIndex;
// Get the number of items of that type:
integer numItemsOfType = llGetInventoryNumber(type);
// For every item in inventory of type:
for (inventoryIndex = 0; inventoryIndex < numItemsOfType; inventoryIndex++) {
// Get the name of the item:
string name = llGetInventoryName(type, inventoryIndex);

// If the item wasn't previously in inventory:
if (llListFindList(oldItems, [name]) == -1) {
// Add the name of the item to addedItems.
addedItems += name;
}
// Add item name to curItems whether it was added or not.
curItems += name;
}
}
// Update the list of inventory.
oldItems = curItems;

// If an item was added to the object's contents:
if (llGetListLength(addedItems) > 0) {
// Do stuff to cope with the added items.
}
}
}
}


The problem with this is that it can be pretty CPU and memory intensive, depending on the number of items in the object's inventory.
==Chris

EDIT: Changed all tabs to four spaces.
EDIT2: More comments.
EDIT3: See next two replies.
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
08-18-2004 11:28
Jeff, and no offense taken. Coding outside of SL is far from my forte.

I'm still unconvinced it would work, regardless - due in part to how permissions and ownership work. That said... would it? I'm too lazy to check in SL right now... :rolleyes:
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
08-18-2004 17:17
argh!! Sorry about the name misspelling, it seems my inability to recognize faces in RL has manifested itself as an inability to spell names in SL :D

Ill correct it asap
==Chris
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
08-18-2004 22:09
From: someone
Originally posted by Jeffrey Gomez
Jeff, and no offense taken. Coding outside of SL is far from my forte.

I'm still unconvinced it would work, regardless - due in part to how permissions and ownership work. That said... would it? I'm too lazy to check in SL right now... :rolleyes:


Im afraid not. llGetOwnerKey only works on objects inside the simulator. Once the object is stored inside of another object, its no longer technically within the simulator; its in the asset server until it is re-rezzed.
==Chris