Jump to content

Getting a ref(!) of a container item?


Recommended Posts

How is it possible (if at all) to get the reference of an item in a container? I can ensure, that:

 

  • The FormID of an item is known
  • The item is unique, so GetItemCount() will always be 1

 

What I was thinking is - OnItemAdded() which would theoretically (at least as it is claimed) deliver me the added reference. Problem is that it only works with persistent references - so, for example, any armor I have in the inventory will be non-persistent. I tried this - and yes, I get the event and the FormID, but no - the reference is empty.

 

I need a reference because in my case it is incorrect to just respawn the object inside the container. If I do that - it "works" at the cost of destroying anything that player could have done to the object - such as mods, renaming etc.

 

Another approach is if there is some way of trying to get the reference of already existing objects in the container - hence by knowing the FormID I then would be able to identify the needed reference. Here I was unable to progress as I'm not aware of any method of retrieving references from the container. Even F4SE to me knowledge only has GetInventoryItems() which will not help me with getting the references.

 

Any ideas on how to do this?

 

EDIT: Why I need it: to add some properties to an object. The flow is: player puts an item in the container from their inventory > presses a button "Add Cool Stuff X" > "Cool Stuff X" is added to an item that they've put into the container > The modified item is returned back to player's inventory.

Edited by Dellecross
Link to comment
Share on other sites

  • 2 years later...

If you know can get the Form of the item (eg by using F4SE's GetInventoryItems Function) you could use something like

ObjectReference objref = ContainerRef.DropObject(FormOfItem,1)
SomeContainerRef.AddItem(objref,1,True)

The first line will drop a random item with the supplied FormID on the ground (the second parameter limits it to one single item).

This function will get you a ReferenceObject if you only drop one.

Since you generally want the item inside the container, you can use the AddItem function to re-add the previously dropped item to a container.

AddItem can work with both Forms and Refs. if you pass a Form, a new item is spawned, but if you pass a ref AND the count is set to 1, the ref will be MOVED to the container.

You may or may not want to move the item back to the original container.

It may be better to process the item on the floor or in a seperate container and only move the item to the original container once you're done.

For a mod I am making, it is necessary to drop the item, move it to a second container and process it there, then move on to the next item. Only once every item from the original container has been processed and consequently is in the second container do I move the entire inventory of this second container back to the original container.

 

I doubt the original author really has use for this, now that almost three years have passed, but I will leave this here for others brought to this thread by google.

Link to comment
Share on other sites

 

What I was thinking is - OnItemAdded() which would theoretically (at least as it is claimed) deliver me the added reference. Problem is that it only works with persistent references - so, for example, any armor I have in the inventory will be non-persistent. I tried this - and yes, I get the event and the FormID, but no - the reference is empty.

 

Non-persistent takeable object references get disabled and deleted by the native game code once an actor ("akActionRef") activates them so you won't be able to get its RefID because it no longer exists. akActionRef's inventory data gets modified accordingly. If it's an editor placed item (so its RefID starts with the load order prefix and not with FF), it won't be actually deleted (not possible) but it will still be marked for deletion so you can no longer call object reference script functions on it reliably.

 

If you'd like to add properties (you meant attaching ObjectMods?), then you can use AttachModToInventoryItem(), RemoveModFromInventoryItem() and RemoveAllModsFromInventoryItem().

 

 

Edit: whoops, just noticed the original post is from 2020..

Edited by LarannKiar
Link to comment
Share on other sites

 

 

What I was thinking is - OnItemAdded() which would theoretically (at least as it is claimed) deliver me the added reference. Problem is that it only works with persistent references - so, for example, any armor I have in the inventory will be non-persistent. I tried this - and yes, I get the event and the FormID, but no - the reference is empty.

 

Non-persistent takeable object references get disabled and deleted by the native game code once an actor ("akActionRef") activates them so you won't be able to get its RefID because it no longer exists. akActionRef's inventory data gets modified accordingly. If it's an editor placed item (so its RefID starts with the load order prefix and not with FF), it won't be actually deleted (not possible) but it will still be marked for deletion so you can no longer call object reference script functions on it reliably.

 

If you'd like to add properties (you meant attaching ObjectMods?), then you can use AttachModToInventoryItem(), RemoveModFromInventoryItem() and RemoveAllModsFromInventoryItem().

How ObjectReference itself is handled inside inventory? For events like OnActivate, OnEquipped etc., can Self be NULL? Assuming Self is nothing else but RefID, as i understand.

Edited by hereami
Link to comment
Share on other sites

How ObjectReference itself is handled inside inventory? For events like OnActivate, OnEquipped etc., can Self be NULL? Assuming Self is nothing else but RefID, as i understand.

 

Inventory items don't send events if I'm remembering right.

 

As for function calls and other internal things, the game doesn't seem to be 100% coherent. For example, if you take an item whose RefID continues to live (so it is either editor placed or persistent), calling Game.GetPlayer().GetDistance(TakenRef) won't return 0 "because it is in the player's inventory" or "because GetDistance fails". It will actually return the distance of the player and TakenRef. And since TakenRef doesn't move anywhere when OnActivate is sent ("when it is picked up"), you can actually measure the distance of the player and TakenRef. However, if TakenRef is held by a quest alias that is shown on the map by a quest objective, the objective would show akActionRef's location and not TakenRef's.

 

It might be worth mentioning that if TakenRef is an editor placed item that is intended to be respawned, upon cell reset, the game undeletes, enables and repositions it. It shouldn't affect akActionRef's inventory at all, though.

 

In my opinion, the typical scenario is when TakenRef gets marked for deletion (and gets deleted if applicable), the atypical ones when both the reference (TakenRef) gets to live and akActionRef's inventory gets modified as well so the same object will have "two lives" (that the developers tried to keep in sync). If you registered a quest for an event from TakenRef (while it wasn't taken yet) for example, "DumpPapyrusEventRegistrations QuestName" would refer to it as something like "<Item x in inventory of (00000014)>" in the Papyrus log. Still, I don't think they send events..

 

By the way, one calls AttachModToInventoryItem like "akActionRef.AttachModToInventoryItem(TakenRef.GetBaseObject(), SomeObjectMod)" so it's a very special function that seems to directly modify akActionRef's inventory while leaving TakenRef practically untouched. Though I suppose this can be verified by F4SE's GetAllMods().. like does TakenRef.GetAllMods() return "SomeObjectMod" that was attached to the inventory item form of TakenRef by "akActionRef.AttachModToInventoryItem(TakenRef.GetBaseObject(), SomeObjectMod)" after TakenRef was picked up?

Edited by LarannKiar
Link to comment
Share on other sites

Well, it's all murkwaters matters, i guess. Probably, Event handlers sitting on objects themselves differ in handling or at least have exclusions, because OnEquipped fires (it wouldn't have any purpose if didn't) and does so even for MiscItem. But yes, OnActivate() doesn't, me forgot.

Edited by hereami
Link to comment
Share on other sites








OnEquipped.Self [SKK_OARingScript <Item 9 in container (00000014)>] Self.GetContainer() [ObjectReference < (00000014)>]

OnUnequipped.Self [SKK_OARingScript <Item 9 in container (00000014)>] Self.GetContainer() [ObjectReference < (00000014)>]

OnContainerChanged.Self [SKK_OARingScript < (FF000EE4)>] akOldContainer [ObjectReference < (00000014)>] akNewContainer None ;drop

OnContainerChanged.Self [SKK_OARingScript <Item 9 in container (00000014)>] akOldContainer None akNewContainer [ObjectReference < (00000014)>] ;pickup

OnContainerChanged.Self [SKK_OARingScript <Item 1 in container (0008A52A)>] akOldContainer [ObjectReference < (00000014)>] akNewContainer [lockExtraLootSCRIPT < (0008A52A)>] ;putin

OnContainerChanged.Self [SKK_OARingScript <Item 9 in container (00000014)>] akOldContainer [lockExtraLootSCRIPT < (0008A52A)>] akNewContainer [ObjectReference < (00000014)>] ;getfrom

Link to comment
Share on other sites

Nice. Guess the above means that Self doesn't provide any usable value except when gets in fresh air?

 

ItemIndex of "<Item N in container (00000014)>" would be a valuable information if we had something like InventoryRef.GetNthForm(N). SKSE has this function but it's missing from F4SE. I think with a modded interface (ContainerMenu) it's possible to send the inventory index of an item from AS3 to Papyrus with F4SE though.

Edited by LarannKiar
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...