How to check if a an index in a table got changed to a different value

For example, mytable = {cool = 8}

mytable.cool = 9

Detect it

I need to detect this change, .__index and .__newindex don’t work for this case.

I need to detect it because if a property of an object was changed for example its attack it needs to change in real time. Just like if you change a position of the part it moves

2 Likes

You are going to need to either fire a function whever it’s changed or everyframe, check if it’s changed by doing something like this
E = mytable.cool
while wait() do
if mytable.cool~=E then
change
end
end

1 Like

Hmm well, I dont really want to use loops, I was wondering if there was any meta method which could help

2 Likes

You need to create a proxy table, one you interact with and has the __newindex method and other where you store the data in

1 Like

How hard is it to just do whatever you need to do when you update it?

1 Like

Ok can you tell me what a proxy table is I never really heard of it

No no, its not really about the complexity its really about how loops seem kinda inefficent , because I will do this for all the properties

1 Like

So instead of directly accessing the table, you are using a proxy, in between you and the other table, which grabs/sets the data from-in other table.

1 Like

Uh could you give an example? I am kinda confused, or any links to help.

local data = {};

local proxy = {};
setmetatable ( proxy , {
__index = data;
__newindex  = function( self , key , value)
        --changed;
         print("Changed");
        data[key] = value;
end;
});

proxy["foo"] = 12;
print(proxy["foo"]);
proxy["foo"] = 15;

Somethings might be wrong cause I typed on mobile.

7 Likes

Ahh ok, I will try to do thanks for the help, if I have any questions can I PM you?

2 Likes

Of course you can. [30 charsss]

2 Likes

Though metatables work for this, I believe a better or more ‘proper’ solution is to send a signal whenever the table is changed. Theoretically, unless you are writing this for somebody else or using third-party scripts in conjunction, you will always have control over what happens with the table. As such, you should also be able to fire a separate function whenever you modify the table in your own scripts. Just food for thought though, as metatables aren’t the worst idea here.

1 Like

Hmm, what do you mean can you explain that a little more?

You have full control over your own scripts.
Whenever you write this

exampleTable.key=10

write this instead

print("Changed key in exampleTable!")
exampleTable.key=10

or for the sake of example

newValue = 10
if exampleTable.key ~= newValue then
    print("key was " .. exampleTable.key .. " and has been changed to " .. newValue)
    exampleTable.key = newValue
end

Oh, yah I was thinking that but I wondered if there was a more idk how to describe it like better? I was using OOP to make a class. I know I could call an update function int he script after changing the property, but I was just seeing if their was a better way

Metatables are great. I love them. They can be messy if you don’t do it right, and I can’t quote any sources here but I remember a lot of remarks about performance or impracticality on the old forum.
They are basically required for OOP. If you are working with OOP, then you need to learn all you can about metatables, it’s pretty simple.
As a basic rundown, you get either a table or a blank userdata (created by newproxy, basically does nothing) and assign a table of functions to it using getmetatable and setmetatable.
If you are going the OOP route, I recommend using newproxy, that looks like this.

local testClass = {}
testClass.New = function(self, Value)
   Value = Value or 5 -- if no Value is given, default to 5.
   local object = newproxy(true) -- don't even ask what this does, you can look it up but it doesn't make much difference.
   -- it just gives a base userdata to modify, and it only accepts 'true' as the argument on Roblox.
   -- you can use a table instead of newproxy, but it has a couple of limitations when using metatables.
   local mt = getmetatable(object)
   mt.__index = function(key) if key=="Value" then return Value else return self[key] end)
   -- this function returns the current Value if you ask for object.Value, otherwise it returns whatever it can find in testClass table.
   -- this is useful because the testClass table would ideally be filled with functions and methods and default properties for this class.
   mt.__add(self, other) -- when this object is added to another
      self.Value = self.Value + other.Value -- I have no safety conditions here, so this will error if the second argument has no 'Value' property.
      return self
   end
   return object
end
testClass.Double = function(self) -- a small function just to demonstrate how to populate the testClass table
   self.Value = self.Value*2
   return self
end

local testObject1 = testClass:New(8) -- create a new testClass object with a Value of 8
local testObject2 = testClass:New() -- create a new testClass with a default Value

print(testObject1) --> userdata blah blah
print(testObject1.Value) --> 8
testObject1 = testObject1 + testObject2 -- Impressive that you can give your classes their own operation functions, yeah?
print(testObject1.Value) --> 12
print(testObject2.Value) --> 5 -- This value was not changed, but we can modify that in the function if we want.
print(testObject1:Double()) --> 24
2 Likes

How about

testClass.__newindex = function(_table, index, value)
-- Content
end

does this method only fire when table[index] tries to be set (table[index] = value), only IF table[index] is nil? Or every time when a table[index], even if it’s value is nil or not, changes

Yes that’s correct, it only fires when a non nil index is set to a value you can try it out in studio. Which is why you need a middle man table to detect it