Table Changed Control From Script

You can write your topic however you want, but you need to answer these questions:

  1. Hey I want to check if a table has changed (got added an instance or not) in every 3 seconds

  2. I have no idea how to do it with my own knowledge

  3. I have tried scripting this thing but It doesnt seem to be working

Any help would be appreciated. How can I exactly detect whenever the table has changed

local plr = game:GetService("Players").LocalPlayer
local enemies = game.Workspace.Enemies
local CombatEnemies = {}

--- SERVICES
local RunService = game:GetService("RunService")

local function enemyCheck()
	
	for i , Enemy in pairs(enemies:GetChildren()) do
		
		local distance = (plr.Character:WaitForChild("HumanoidRootPart").Position - Enemy:WaitForChild("HumanoidRootPart").Position).Magnitude
		
		if distance < 100 then
			
			if not CombatEnemies[Enemy] then
				CombatEnemies[Enemy] = true
			end			
			
		end
			
		if distance > 100 and CombatEnemies[Enemy] == true then
			
			CombatEnemies[Enemy] = nil
			
		end
		
	end
end

local function TableChange()
	
	while true do
		task.wait(3)
		
		local CurrentSet = {}
		
		enemyCheck()
		
		if #CurrentSet ~= #CombatEnemies then
			
			CurrentSet = CombatEnemies
			
		end
		
		
	end
	
end




Any ideas?

  1. you can either use Variable for that or BoolValue(whatever you want)
  2. No problem, dev in here always help
  3. you can improve
    i’ve been answered all your questions, the Script look fine to me but, you could change CombatEnemies[Enemy] = nil to CombatEnemies[Enemy] = false (Optional) also change local function to function (Optional), overall the Script is fine!, just dont mess it up
1 Like

You can also use setmetatable to intercept the changes to the table without using any kind of loop.

For example:

local data = {}
local CombatEnemies = {}

function updated() 
    print("there was a change to the table")
end

setmetatable(CombatEnemies, {
    __index = function(_, key)
        return data[key]
    end,
    __newindex = function(_, key, value)
        local oldValue = data[key]
        if value == nil then
            if oldValue ~= nil then
                data[key] = nil
                updated() -- something was removed
            end
        elseif oldValue == nil then
            data[key] = value
            updated() -- something was added
        else
            data[key] = value
            updated() -- something was updated
        end
    end,
    __pairs = function()
        return next, data, nil
    end,
    __len = function()
        return #data
    end
})

Then if you do a change like this:

CombatEnemies.Zombie = 1

It will trigger the updated function.

1 Like

also you might asking why
change CombatEnemies[Enemy] = nil to CombatEnemies[Enemy] = false
i see that your Script have CombatEnemies[Enemy] = nil So it just hurt my eyes, that you didnt use boolean for it
also you asking about why change local function to function lemme explain clearly in basic term
function is basically a function that defined on top of code, to visual this imagine a gun, when you shoot a gun yeah you see it function outside, but it also has local function inside which is the mechanics of a gun

1 Like

I have never used metatables before
do you have any good video tutorial on them?

I used chatgpt for adding instances into table and he said If I do false I dont remove it from the table I just make it’s value false and I didnt want that
thats why I used nil

Thanks for the explanation

Just found this video - maybe useful to you.

The metatable (__index, __newindex, __pairs, __len) are just metamethods which are methods that let you change how table’s behave when certain operations happen within them - almost like they are hooks.

So the code I gave you sets the metatable to overhook __newindex to fire the updated function on changes.

Only __newindex is relevant in the example I gave but I just kept the others there to preserve the functionality of the table (e.g. __pairs is for looping, __index is for fetching data and __len for getting the table length).

1 Like

Also Unrelated to topic

Do you think handling all thugs from one script is efficient?

I feel so bad that I have been trying to learn script for 2 years now but still struggle at stuff like these

If it’s well maintained then yeah it can be okay.

I prefer breaking everything up into different scripts though, mainly ModuleScripts and then just make the functions and data exported from them - makes maintenance and debugging much easier anyway.

(You never stop learning programming, there is no end)

So how many scripts you end up with when you finish a game usually?

Depends on what kind of game.

My most recent game probably has around 40-50 different scripts with 80% of them just being module scripts that return different data and functions to be used.

1 Like

You can also combine metatables with Variable or BoolValue as i mentioned earlier to work together for some purposes

1 Like

I really wanna learn this type of scripting but I use much more of server scripts and local scripts on their own

I gotta go and understand metatables now
I will mark this as a solution If I find a way to use them

Thanks a lot

Just try using this with your current code and see if it works as you wish but yea I would advise you do learn them.

Just remove your declaration of CombatEnemies and simply paste this at the top of your script.

local data = {}
local CombatEnemies = {}

function updated() 
    print("there was a change to the table")
end

setmetatable(CombatEnemies, {
    __index = function(_, key)
        return data[key]
    end,
    __newindex = function(_, key, value)
        local oldValue = data[key]
        if value == nil then
            if oldValue ~= nil then
                data[key] = nil
                updated() -- something was removed
            end
        elseif oldValue == nil then
            data[key] = value
            updated() -- something was added
        else
            data[key] = value
            updated() -- something was updated
        end
    end,
    __pairs = function()
        return next, data, nil
    end,
    __len = function()
        return #data
    end
})

And I’ll just again briefly explain why it works and what’s happening.

Essentially CombatEnemies just becomes a proxy for data - you can see I am setting the metamethods to update the values inside of the “data” table instead of the CombatEnemies and also I am returning the values from “data”.

That way when you do CombatEnemies[key] for example it’s actually doing data[key] - the difference is in the __newindex (a value change) so if a value is changed then it will trigger updated AND also update the data - I broke it up into 3 things (removal, added, updated) incase you wanted to use that in future.

Happy to help.

I really dont understand anything from this code when I look at it so I better go and get good at metatables

Meanwhile
me : lowkey painfully writing whole backend-frontend, 100-1000 lines of codes, 100-200+ configs system im really tired, even the codes are working, no error at all, good codes, im just tired so that why ppl have devs team, and im just solo

1 Like