Creature.__index = function(tab , index) return rawget(tab , index) or rawget(Creature , index) or warn("indexed " .. index .. ", is " .. tostring(rawget(tab , index)) .. ". line #" .. tostring(debug.info(2, "l")) , tab) end
Creature.__newindex = function(Table , Key , Value)
print(Key)
if Key == "Energy" or Key == "Health" then
rawset(Table , Key , math.clamp(math.floor(Value + 0.5) , 0 , math.huge))
print("HEALTH OR ENERGY CHANGED")
elseif Key == "StatusEffect" and Table.StatusEffect == "Healthy" then
print(Table)
rawset(Table , Key , Value)
else
rawset(Table , Key , Value)
end
end
I was working on a class for my game, but then i realised that metatables were not printing out any thing, despite the metamethods definitely being called at some point, as i did change some value.
That said the index metamethod shown here works for some reason.
Oh! I see what you mean now. I’ve run into this problem before and was just as confused. It turns out that the __newindex metamethod only fires when a new property is indexed. In other words, the property that you are trying to change cannot be directly in the table or metatable. It’s dumb that we don’t have an event to detect when a property changes, but it is what it is. In order to circumvent this, you have to use a proxy table.
Basically you need to create a proxy table that you store the variables you want __newindex to fire on.
An example might be this:
local example = setmetatable({result = {}}, {
__tostring = function()
return "Example" -- the name
end,
__index = function(proxy, key)
local result = rawget(proxy,"result")
if result[key] ~= nil then
print(string.format("%q was accessed", key))
else
error(string.format("%s is not a valid member of %s %q", key, tostring(proxy), tostring(proxy)))
end
return result[key]
end,
__newindex = function(proxy, key, value)
local result = rawget(proxy,"result")
if result[key] ~= nil then -- shows what action is being done
if value == nil then
print(string.format("%q was deleted", key))
elseif result[key] ~= value then
print(string.format("%q was changed", key))
end
else
print(string.format("%q was set", key))
end
result[key] = value -- set the value
end
})
print(example)
example.test = true -- "test" was set
example.test = false -- "test" was changed
print(example.test) -- "test was accessed
-- false
example.test = nil; -- "test" was deleted
print(example.test) -- Error: test is not a valid member of Example "Example"
Note: Setting this up with the table you use being the proxy means that Roblox’s type-inference engine won’t be able to tell what variables are being stored in the table. However, you can fool it using type checking.
I don’t undersand what you’re doing differently, you’re still using the newindex metamethod, and the index metamethod does nothing but error when you set something that isn’t in the proxxy table. why does this work differently?
Also would this error if something is on the table but not on the proxy table, and then you index that?
Ah i see now, so the proxy table is actually kept empty so index and newindex can always trigger, and the metamethods return references to the real table, clever.
Just a bit confused by your response here. Are you having any additional troubles or were you just puzzling how it worked? If so, then you can just dm me.