Jump to content

Recommended Posts

Hi,

 

I'm attempting to make a type of gem that, when placed in a container, will affect all the items in that container - including ones put in later. to do this i've given this prefab a custom component, "inventorychanger". However, I'm having a couple of issues.

 

Firstly, I don't know how to correctly remove event listeners from an entity. When the gem is placed in a container, it adds an event listener to the container so it is told when items are inserted and removed (to start/stop affecting them respectively) using the following code called when the inventorychanger is placed in a container:

function InventoryChanger:OnPutInInventory(container)	if self.container and self.onremovedfn then		self.onremovedfn(self.inst, self.container)	end	if self.container and self.container.components.container then		self.container:RemoveEventCallback("itemget", self.ItemInFn)		self.container:RemoveEventCallback("itemlose", self.ItemOutFn)	end	self.slotreg = {}	self.container = container	if self.container.components.container then		self:UpdateSlotRegistry()		self.container:ListenForEvent("itemget", function(inst, data) self:ItemInFn(data) end)		self.container:ListenForEvent("itemlose", function(inst, data) self:ItemOutFn(data) end)			end	if self.onputinfn then		self.onputinfn(self.inst, self.container)	endend

however, the lines removing the event callback do not work - upon removing and replacing the gem in the container several times, ItemInFn is calleed several times as well when a new item is put into the container. Ive tried with the exact same function as the the ListenForEvent lines as the second argument, and with no second argument at all, to no avail. does anyone know the correct syntax to do this?

 

 

My second problem is with the "slot registry" (or self.slotreg). this is a table of all the items in the container, used to find out which item was removed. This is required because the "data" supplied by the event "itemget" includes both the entity inserted into the container and the slot it was put into, where as the data given by "itemlose" only includes the slot number. the logic here is that when an item is removed, it checks what entity was at the slot number it was removed from, and does whatever it needs to to said entity. however, ive found that by the time "itemlose" has been pushed and listened to, somehow the slot registry has already been updated and the item being removed has prematurely been removed.

 

for example, at the moment ItemOutFn is merely

function InventoryChanger:ItemOutFn(data)    removed = self.slotreg[data.slot]	print("removed",removed.prefab)    --DoSomething(removed)	table.remove(self.slotreg, data.slot)end

but it consistently throws the error attempt to index field '?' (a nil value) on line 2, because self.slotreg no longer has data at the index of data.slot that is passed in (ive checked, and its still populated with everything else in the container).

 

This remains true even when i remove the line self:UpdateSlotRegistry() from the code above (the only place where that function is called) 

 

if anybody could help with either of these problems, i would be eternally grateful!

Edited by MigratoryCoconuts

@MigratoryCoconuts,

 

Regarding the first problem. You are adding an event listener with an anonymous function. It has no reference. Then you are trying to remove the event from a named function which is called from within your anonymous function.

 

Change these two lines

self.container:ListenForEvent("itemget", function(inst, data) self:ItemInFn(data) end)self.container:ListenForEvent("itemlose", function(inst, data) self:ItemOutFn(data) end)

to this:

self.container:ListenForEvent("itemget", self.ItemInFn)self.container:ListenForEvent("itemlose", self.ItemOutFn)

If "inst" and "data" are being correctly passed into your anonymous function, They should also be passed into your named function like this.

 

 

 

And for the second, you could keep a local array of the items' prefabs yourself, indexed the same way as the original.

local slot_prefabs = {}function InventoryChanger:ItemInFn(data)    slot_prefabs[data.slot] = data.item.prefab    -- ...endfunction InventoryChanger:ItemOutFn(data)    local prefab = slot_prefabs[data.slot]    print(prefab)    -- ...end

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...