"Unable to cast value to function" error

Ok, I will be away at the moment to look into this. I will let you know when I come to a solution

I thought I’d let you know, I changed the first function, where the event is received by the server, since I noticed the function wasn’t fully running through.

dataEvent.OnServerEvent:Connect(function(plr,newData)
	for index, val in pairs(data) do
		for _, plrName in pairs(game.Players:GetPlayers()) do
			if plrName.Name == plr.Name then
				table.remove(data, index)
				table.insert(data, index, newData)
			end
		end
	end
end)

The line I changed:

for _, plrName in pairs(game.Players:GetPlayers()) do
			if plrName.Name == plr.Name then

Edit:
I changed this for all the functions this happened for, and replaced the value in saveData(plr,value) with the val variable.

Thought I’d let you know, I figured out how to finish this. So I basically totally re-wrote the part that saves data. It works in game now. Here’s the local script:

local plr = game.Players.LocalPlayer
local dataEvent = game.ReplicatedStorage:WaitForChild("DataEvent")

local lvl = 1 --set 1
local exp = 0 -- set 0
local expToNextLvl = 100 -- set 100
local lvlMult = 1.1 -- set 1.1

--[[coroutine.resume(coroutine.create(function()
	local currentLvl = lvl
	
	repeat wait() until currentLvl == lvl
	expToNextLvl = expToNextLvl*lvlMult
end))]]

coroutine.resume(coroutine.create(function()
	while wait(.5) do
		if exp >= expToNextLvl then
			lvl = lvl+1
			lvlMult = lvlMult+.1
		end
	end
end))

local data = {
	[1] = lvl,
	[2] = exp,
	[3] = expToNextLvl,
	[4] = lvlMult
}

local saveDb = true

coroutine.resume(coroutine.create(function()
	dataEvent.OnClientEvent:Connect(function(newlvl,newexp,newexpToNextLvl,newlvlMult)
		if saveDb then
			saveDb = false
			lvl = newlvl
			exp = newexp
			expToNextLvl = newexpToNextLvl
			lvlMult = newlvlMult
		end
		while wait(.1) do
			dataEvent:FireServer(data)
		end
	end)
end))

Here’s the server script:

local DS = game:GetService("DataStoreService")
local expDataStore = DS:GetDataStore("PlrEXP")
local dataEvent = game.ReplicatedStorage:WaitForChild("DataEvent")

local data = {
	[1] = nil,
	[2] = nil,
	[3] = nil,
	[4] = nil
}
local newlvl = nil
local newexp = nil
local newexpToNextLvl = nil
local newlvlMult = nil

game.Players.PlayerAdded:Connect(function(plr)
	local plrId = "Player_"..plr.UserId
	
	local plrData
	local success, err = pcall(function()
		plrData = expDataStore:GetAsync(plrId)
	end)

	if success then
		print(plrData)
		for index,val in pairs(plrData) do
			if index==1 then
				newlvl = val
				data[1] = val
			elseif index==2 then
				newexp = val
				data[2] = val
			elseif index==3 then
				newexpToNextLvl = val
				data[3] = val
			elseif index==4 then
				newlvlMult = val
				data[4] = val
			end
		end
		print("\n"..newlvl.." lvl\n"..newexp.." exp\n"..newexpToNextLvl.." exp to nxt lvl\n"..newlvlMult.." lvl mult")
		dataEvent:FireClient(plr,newlvl,newexp,newexpToNextLvl,newlvlMult)
	else
		warn(err)
	end
end)

local db = true

dataEvent.OnServerEvent:Connect(function(plr,newData)
	for _,newPlr in pairs(game.Players:GetPlayers()) do
		if newPlr.Name == plr.Name then
			if db then
				db = false
				for index,val in ipairs(newData) do
					if index==1 then
						newlvl = val
						data[1] = val
					elseif index==2 then
						newexp = val
						data[2] = val
					elseif index==3 then
						newexpToNextLvl = val
						data[3] = val
					elseif index==4 then
						newlvlMult = val
						data[4] = val
					end
					coroutine.resume(coroutine.create(function()
						local cdb = true
						if cdb then
							cdb = false
							game.Players.PlayerRemoving:Connect(function()
								local plrId = "Player_"..plr.UserId
								local success, err = pcall(function()
									expDataStore:SetAsync(plrId,data)
								end)
								if err then
									warn(err)
								end
							end)
							cdb = true
						end
					end))
				end
				db = true
			end
		end
	end
end)

So to get around the table problem. I created a table in the server script with 4 key’s already set to nil. And when I introduced the new table, I had the same key’s set up and detected when the first key came up, and transferred the data from that key to the new corresponding key, same for 2-4.