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.
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.  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. If only there were an llGetCreator/llGetCreatorName... though, even that would not solve the problem.  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.
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. 
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.
If only there were an llGetCreator/llGetCreatorName... though, even that would not solve the problem. 
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: // 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... 
|
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  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... 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
|