Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Table changed, help?

Asked by
Turgon 80
9 years ago

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?

2 answers

Log in to vote
2
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

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!

Ad
Log in to vote
0
Answered by 9 years ago

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!

Answer this question