ObjectRefs, Containers, OnItemRemoved() & Lvd Items

Post » Sat Nov 17, 2012 8:07 am

Incomprehensible and unfixable issue with a mix of these four things. Description :


1) Here's a vanilla Container with n Items, all coming from Lvd Lists. THIS is the key of the problem

2) Player picks one Item, its Ref is registered in an ObjectReference[] by scripts. As it is the first, index = 0

3) Player continues to pick Items one by one, repeating 2) until there's only one Item left (n - 1) in the Container. Until this moment included, the Items already in Player Inventory can be dropped, put back in their original Container or another one, they will always be recognized as (akItemReference) from a Player Alias OnItemRemoved().

4) But now if Player takes the last Item and so the Container is empty, this last ObjectReference is NOT recognized if i put it back in its Container, not because the ObjectReference[i] is not matching, but because (akItemReference) is NULL !


A few more details :

- Player OnItemRemoved(akItemReference) is though not equal to None for the last ObjectReference[] index, if dropped on the ground or in most of others Containers (but not all)
- No problem with the others ObjectReference[i]
- No problem at all with the last Item if all the Items are NOT coming from Lvd Lists.
- No problem at all (even if Items come from Lvd Lists) if Container is an Actor, living or dead
- Once the problem occured, if i take back the last Item from Container to Inventory, it will be given the next index of the array, the system considering it as new. But from there, this new ObjectReference[i] will finally be recognized in EVENT OnItemRemoved() to its original Container. It's usually the case, but not all the time though.

Skyrim 1.6 + corresponding SKSE
No others mods than this one and SkyUI

I can't figure what's happening. Any idea ?
User avatar
Rachel Briere
 
Posts: 3438
Joined: Thu Dec 28, 2006 9:09 am

Post » Sat Nov 17, 2012 4:31 am

Only persistent references and References filling quest aliases will reliably register as anything other than 'None'. Forms spawned in containers, created items, forms from LVLIs, etc. are just abstractions 'til they render. Once dropped, items should have and retain FormIDs as ObjectReferences, although I'm not sure about the engine's object permanence (like how long it'll retain the FormID or if it's saved).

Try a FormList rather than an array and make sure, either way, that you're not checking a -1 element, an empty element, or beyond the end/beginning of the array/list you're using. Really, a FormList would be better for temporarily storing dropped item references as it'll not accept 'None' and GetSize will return the appropriate number while Length will return the total number of elements even if some are 'None'.

Spoiler
This works:
  • Player Alias
    State Catch	Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference)		If akBaseObject != BagOfHoldingARMO			ObjectReference rObject = BagOfHoldingDroppedItemFLST.AddForm(PlayerREF.DropObject(akBaseObject)) 			If rObject				rObject.Disable()			EndIf		EndIf	EndEventEndStateFunction Strip(Int aiSlot = 43, String asInitialState = "")	asInitialState = GetState()	GoToState("Catch")	While aiSlot > 30		aiSlot -= 1		PlayerREF.UnequipItemSlot(aiSlot)		Utility.WaitMenuMode(0.01)	EndWhile	GoToState(asInitialState)EndFunction
  • Container
    	aiIndex = BagOfHoldingDroppedItemFLST.GetSize()	While aiIndex > 0		aiIndex -= 1		arObject = BagOfHoldingDroppedItemFLST.GetAt(aiIndex) As ObjectReference		arObject.Enable()		arObject.Activate(PlayerREF)		PlayerREF.EquipItem(arObject.GetBaseObject(), False, True)	EndWhile
User avatar
Sheeva
 
Posts: 3353
Joined: Sat Nov 11, 2006 2:46 am

Post » Fri Nov 16, 2012 8:01 pm

Once dropped, items should have and retain FormIDs as ObjectReferences, although I'm not sure about the engine's object permanence (like how long it'll retain the FormID or if it's saved).

I can confirm that this isn't always the case. I have had many instances where an item's ObjectReference was NONE, even when the item was dropped into the world. These were items added to the player's inventory directly from a script via their base object (not a persistent reference in the world). The only way I've seen to reliably know that something will have an ObjectReference is to place it into the world using the CK.

In general, dealing with objectreferences of items that can be placed inside a container or picked up by the player is unreliable.
User avatar
Jynx Anthropic
 
Posts: 3352
Joined: Fri Sep 08, 2006 9:36 pm

Post » Fri Nov 16, 2012 7:05 pm

Only persistent references and References filling quest aliases will reliably register as anything other than 'None'. Forms spawned in containers, created items, forms from LVLIs, etc. are just abstractions 'til they render. Once dropped, items should have and retain FormIDs as ObjectReferences, although I'm not sure about the engine's object permanence (like how long it'll retain the FormID or if it's saved).

Try a FormList rather than an array and make sure, either way, that you're not checking a -1 element, an empty element, or beyond the end/beginning of the array/list you're using. Really, a FormList would be better for temporarily storing dropped item references as it'll not accept 'None' and GetSize will return the appropriate number while Length will return the total number of elements even if some are 'None'.

Thanks Justin, so i gave a try on both, but unfortunately it's the same as using arrays. I'm sure that the test RefAlias is well forced to the last ObjectReference[], and that List.GetSize() has the proper value, but no way. Whatever can be the number of Items, as long as they come from Lvd Lists the last one is always "nullified" if i put it back in its original Container, and so not recognized. But this last Item taken is not "nullified" if i drop it on the ground, or if i put it in Breezehome Chests for example. CRAZY.

As it though works with these conditions, i don't think it's a persistence problem, but i've no idea where it comes from. I am 100% sure that ObjectReference[n -1] is correctly filled, with a Notification verification. The array is also a Property and not just a variable.

I can confirm that this isn't always the case. I have had many instances where an item's ObjectReference was NONE, even when the item was dropped into the world. These were items added to the player's inventory directly from a script via their base object (not a persistent reference in the world). The only way I've seen to reliably know that something will have an ObjectReference is to place it into the world using the CK.

In general, dealing with objectreferences of items that can be placed inside a container or picked up by the player is unreliable.

Strange, any time i dropped an Item on the ground, even if it was coming from AddItem, (akItemReference) has always be equal to something and not Null. This is how i'm filling the ObjectReference[] at first, before i take them back, and the indexes are correctly filled because a Notification shows on every Ref re-added to the Player. The problem only occurs when i put the last Item taken back in its Container.


P.S. : i will edit OP to provide a few more details.
User avatar
JeSsy ArEllano
 
Posts: 3369
Joined: Fri Oct 20, 2006 10:51 am


Return to V - Skyrim