Im trying to make an Inventory system, it works as a table and a GUI.. I have a function to sort the GUI by checking the table. Would it be possible to run the function when table is changed, like in values?
I tried this;
InvMuch = #PlyrInv InvMuch.Changed:connect(SortSlots)
But it doesn't work. Any ideas?
The connect
syntax is a special thing that ROBLOX made for its own objects. Developing that syntax for your objects is not preferable.
You can use a loop as someone else mentioned, but it requires knowledge of the table (what to watch), and potentially could miss some changes.
Instead, we can use creative metatable solutions to do this.
local inventory = {}; local fake = {}; function onChange(key) -- Do stuff print("CHANGED",key,"TO",inventory[key]); end local recursive = false; local meta = { __index = function(key) return fake[key]; end, __newindex = function(_,key,value) print("SETTING!"); fake[key] = value; recursive = true; if not recursive then -- This condition is an optional feature. -- It would make changes made by the `onChange` function -- NOT fire `onChange` again (which at times may be -- very convenient) onChange(key); end recursive = false; end }; setmetatable(inventory,meta);
This method has a number of drawbacks, unfortunately. A number of built in functions do not work with this for technical reasons:
pairs
ipairs
table.insert
table.remove
. These all can technically be remedied by redefining them, however, that would be an annoying project.
Robust loop approach:
While a loop cannot manage to capture instantaneous changes, it can at least track changes from time to time. A robust solution would automatically capture all visible changes, and not just those on a select number of variables. We can do that like this:
local old = {}; function watch(tab) if not old[tab] then old[tab] = {}; end local exist = {}; for index,value in pairs(tab) do if old[tab][index] ~= value then Changed(index,tab); end old[tab][index] = value; exist[index] = true; end for index in pairs(old[tab]) do if not exist[index] then Changed(index,tab); old[tab][index] = nil; end end end
In some external loop (or using the Stepped
event or similar) we continually call watch
on the table we want to watch. This function in turn will call Changed
for any values which are different from the last call to watch
.
This is robust because it requires no knowledge of which values you need to watch, and will work for all. However, if you ever redefine a list completely, e.g., inventory = {};
then the change of deleting them will not be found. In this case, I designed watch
to have a second, optional, "name" parameter. This is used to identify tables instead (when provided), so if you want to be able to clear out a table, you can pass "inventory"
as the second parameter to watch
.
(This is of course all just an example and your implementation could vary)
Good luck!
You could always use a loop:
local PreviousPlyrInv = PlyrInv while wait() do repeat wait() until PlyrInv ~= PreviousPlyrInv --This basically makes the loop wait until the PreviousPlyrInv is not equal to the PlyrInv, which is making the loop wait until the table is changed PreviousPlyrInv = PlyrInv --This sets the PreviousPlyrInv to the PlyrInv so that it only executes the code below once, until the table is changed again --Do code end
Hope this helped!