Difference between revisions of "OnItemAdded - ObjectReference"

From the CreationKit Wiki
Jump to navigation Jump to search
imported>Layam
(Added note about using this event to force-equip items in a pick-pocketting or OpenInventory() dialogue.)
imported>Quindraco
 
(11 intermediate revisions by 2 users not shown)
Line 14: Line 14:
*akBaseItem: The base object for the item that was added to this container.
*akBaseItem: The base object for the item that was added to this container.
*aiItemCount: The number of items added to this container.
*aiItemCount: The number of items added to this container.
*akItemReference: The specific reference added to the container, if any. Will be None if a non-persistant object is added.
*akItemReference: The specific reference added to the container, if any. Will be None if a non-persistent object is added.
*akSourceContainer: The container that the object(s) came from. If None, then the object came from the world.
*akSourceContainer: The container that the object(s) came from. If None, then the object came from the world.


Line 33: Line 33:
*Once an object has been added to a container it is no longer valid to call member functions on it. Member functions on akItemReference (which is often None) will most likely fail to run with an error.
*Once an object has been added to a container it is no longer valid to call member functions on it. Member functions on akItemReference (which is often None) will most likely fail to run with an error.
*If you only care about certain kinds of objects, you should also use [[AddInventoryEventFilter - ObjectReference|AddInventoryEventFilter]] to filter out any events for things you aren't interested in.
*If you only care about certain kinds of objects, you should also use [[AddInventoryEventFilter - ObjectReference|AddInventoryEventFilter]] to filter out any events for things you aren't interested in.
*Although you can use this event to force actors to equip items in an [[OpenInventory - Actor|OpenInventory]] or pick-pocketing dialogues, those items will not be visible until the dialogue is ended. Calling the SKSE function [[QueueNiNodeUpdate - Actor|QueueNiNodeUpdate]] straight after calling EquipItem can force the actor to draw the new equipment immediately.
**If the player takes a large number of items out of a container (e.g. by using the Take All feature while in their home), an OnItemAdded event handler that doesn't use an inventory filter will be queued to run for each type (base form) of item that the player removes. If a container has a considerably large variety of items inside, too many OnItemAdded calls will accrue, severely overburdening Skyrim's script engine and triggering warnings (this is called "dumping stacks"). By contrast, an OnItemAdded handler with an event filter won't even be queued to run unless the item being added matches that filter; that handler won't cause stack dumping unless the player adds a huge number of the specific item that the handler is looking for, and even that would only happen if the player added all of those items one-by-one.
**Problems can also occur if the player picks up a large number of items in rapid succession (e.g. because they're thoroughly looting an interior, or because they like picking flowers as they walk). If your OnItemAdded handler is slow (perhaps it accesses a shared resource, such as the player), and if you're not using an inventory event filter, then queued OnItemAdded calls can pile up. Chances are good that the player will eventually stop picking up items and give your script calls enough time to finish, but if the player ''doesn't'' stop for a long enough while, then your script may eventually cause Skyrim to dump stacks.
*If you need to temporarily stop OnItemAdded and OnItemRemoved calls from being queued, you can use AddInventoryEventFilter with an empty FormList as an argument. To resume listening for item additions and removals, you can call [[RemoveAllInventoryEventFilters - ObjectReference|RemoveAllInventoryEventFilters]].
**This trick stops OnItemAdded calls from ''being queued.'' It doesn't prevent the execution of function calls that have already been queued. To wit, using this trick from inside of OnItemAdded won't stop Skyrim from dumping stacks when you Take All from a QASmoke container, because the first OnItemAdded call only executes after the other hundred or so have been queued. Rather, you'd want to stop listening to inventory events from elsewhere (e.g. an OnMenuOpen event checking for inventory menus, if you don't mind relying on SKSE).
*Remember that you can point multiple reference aliases at the player. Each can have their own inventory event filters and inventory event handlers, so you can filter OnItemAdded and OnItemRemoved differently.
*If you call RemoveItem from this event handler, it ''does'' fire an OnItemRemoved event. This can lead to a tricky situation if you need to reject certain items, but ''also'' detect if the player manually removes an item (e.g. a full bookshelf rejecting a deposited book, without mistaking its own rejection for a withdrawal).
**You can use the AddInventoryEventFilter and an empty FormList to stop events from being fired immediately before you call RemoveItem; and then resume events with RemoveInventoryEventFilter. There will be a very brief window of time during which another added item may go unnoticed, but generally this is the best method to avoid confusing rejections and withdrawals.


== See Also ==
== See Also ==

Latest revision as of 15:08, 8 June 2018

Member of: ObjectReference Script

Event received when an item is inserted into this object's container.

Syntax[edit | edit source]

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)

Parameters[edit | edit source]

  • akBaseItem: The base object for the item that was added to this container.
  • aiItemCount: The number of items added to this container.
  • akItemReference: The specific reference added to the container, if any. Will be None if a non-persistent object is added.
  • akSourceContainer: The container that the object(s) came from. If None, then the object came from the world.

Examples[edit | edit source]

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
  if !akSourceContainer
    Debug.Trace("I picked up " + aiItemCount + "x " + akBaseItem + " from the world")
  elseif akSourceContainer == Game.GetPlayer()
    Debug.Trace("The player gave me " + aiItemCount + "x " + akBaseItem)
  else
    Debug.Trace("I got " + aiItemCount + "x " + akBaseItem + " from another container")
  endIf
endEvent

Notes[edit | edit source]

  • Once an object has been added to a container it is no longer valid to call member functions on it. Member functions on akItemReference (which is often None) will most likely fail to run with an error.
  • If you only care about certain kinds of objects, you should also use AddInventoryEventFilter to filter out any events for things you aren't interested in.
    • If the player takes a large number of items out of a container (e.g. by using the Take All feature while in their home), an OnItemAdded event handler that doesn't use an inventory filter will be queued to run for each type (base form) of item that the player removes. If a container has a considerably large variety of items inside, too many OnItemAdded calls will accrue, severely overburdening Skyrim's script engine and triggering warnings (this is called "dumping stacks"). By contrast, an OnItemAdded handler with an event filter won't even be queued to run unless the item being added matches that filter; that handler won't cause stack dumping unless the player adds a huge number of the specific item that the handler is looking for, and even that would only happen if the player added all of those items one-by-one.
    • Problems can also occur if the player picks up a large number of items in rapid succession (e.g. because they're thoroughly looting an interior, or because they like picking flowers as they walk). If your OnItemAdded handler is slow (perhaps it accesses a shared resource, such as the player), and if you're not using an inventory event filter, then queued OnItemAdded calls can pile up. Chances are good that the player will eventually stop picking up items and give your script calls enough time to finish, but if the player doesn't stop for a long enough while, then your script may eventually cause Skyrim to dump stacks.
  • If you need to temporarily stop OnItemAdded and OnItemRemoved calls from being queued, you can use AddInventoryEventFilter with an empty FormList as an argument. To resume listening for item additions and removals, you can call RemoveAllInventoryEventFilters.
    • This trick stops OnItemAdded calls from being queued. It doesn't prevent the execution of function calls that have already been queued. To wit, using this trick from inside of OnItemAdded won't stop Skyrim from dumping stacks when you Take All from a QASmoke container, because the first OnItemAdded call only executes after the other hundred or so have been queued. Rather, you'd want to stop listening to inventory events from elsewhere (e.g. an OnMenuOpen event checking for inventory menus, if you don't mind relying on SKSE).
  • Remember that you can point multiple reference aliases at the player. Each can have their own inventory event filters and inventory event handlers, so you can filter OnItemAdded and OnItemRemoved differently.
  • If you call RemoveItem from this event handler, it does fire an OnItemRemoved event. This can lead to a tricky situation if you need to reject certain items, but also detect if the player manually removes an item (e.g. a full bookshelf rejecting a deposited book, without mistaking its own rejection for a withdrawal).
    • You can use the AddInventoryEventFilter and an empty FormList to stop events from being fired immediately before you call RemoveItem; and then resume events with RemoveInventoryEventFilter. There will be a very brief window of time during which another added item may go unnoticed, but generally this is the best method to avoid confusing rejections and withdrawals.

See Also[edit | edit source]