MigratoryCoconuts Posted January 21, 2015 Share Posted January 21, 2015 (edited) 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) endendhowever, 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 merelyfunction InventoryChanger:ItemOutFn(data) removed = self.slotreg[data.slot] print("removed",removed.prefab) --DoSomething(removed) table.remove(self.slotreg, data.slot)endbut 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 January 21, 2015 by MigratoryCoconuts Link to comment https://forums.kleientertainment.com/forums/topic/49485-changing-the-behaviour-of-a-container-via-an-item-within-it/ Share on other sites More sharing options...
Blueberrys Posted January 26, 2015 Share Posted January 26, 2015 @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 linesself.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 Link to comment https://forums.kleientertainment.com/forums/topic/49485-changing-the-behaviour-of-a-container-via-an-item-within-it/#findComment-606092 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now