What script? the metatable script?
Yes, the metatables script
Since the Humanoid.Running gets the client speed its this code:
local mt = getrawmetatable(game)
local oldindex = mt.__index
setreadonly(mt,false)
mt.__index = function(indexed,property)
if indexed == "Humanoid" and property == "WalkSpeed" then
return 16 -- or whatever speed value
end
return oldindex(indexed,property)
end
setreadonly(mt,true)
oh I’m an idiot, I could’ve just straight copied the sample code from the tutorial.
Lol, true. It’s on the top by the original author.
Can Exploiters change attributes?
anything you can do an exploiter can do plus alot more
You need to learn more about how to use module correctly
Wrong:
function self:SafeKickClient(Message)
local Success, Error = pcall(function() game:GetService("Players").LocalPlayer:Kick(Message) end)
local StatsService = game:GetService("Stats")
RunService.RenderStepped:Wait()
if not Success or StatsService.DataSendKbps ~= 0 then
repeat until true ~= true
end
end
Lead function located named self? Huh.
Also useless using RenderStepped as wait/sleep
Correct & Better:
local Module = {}
Module.__index = Module
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Storage
if RunService:IsServer() then
if not Storage or not script:FindFirstChild("Folder") then
Storage = Instance.new("Folder", script)
else
Storage = script:WaitForChild("Folder", 15)
end
else
Storage = script:WaitForChild("Folder", 15)
end
function Module.init()
return setmetatable({}, Module)
end
function Module:findObject(name: string, withInstance: boolean)
-- prevent error by exploited
assert(typeof(name) == "string", "Invalid type of player name.")
if Storage and Storage:IsA("Folder") and Storage:FindFirstChild(name) then
if withInstance then
return {true, Storage:WaitForChild(name)}
end
return true
end
if withInstance then
return {false, nil}
end
return false
end
-- decated function only for server
If RunService:IsServer() then
function Module:Add(playerName: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(playerName:len() > 0, "Invalid minimum player name length")
if not self:findObject(playerName) then
Instance.new("IntValue", Storage).Name = playerName
return self:findObject(playerName)
end
return false
end)
function Module:Remove(playerName: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(playerName:len() > 0, "Invalid minimum player name length")
local GetObject = self:findObject(playerName, true)
if GetObject and GetObject[1] == true then
GetObject[2]:Destroy()
return true
end
return false
end)
end
function Module:SafeKickClient(playerName: string, Message: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(typeof(Message) == "string", "Invalid type of message or message is required.")
if RunService:IsClient() and Players.LocalPlayer then
assert(Players.LocalPlayer.Name == playerName, "Are you trying to using other person name?.")
return
end
local GetObject = self:findObject(playerName, true)
if GetObject and GetObject[1] == true then
if Players:FindFirstChild(playerName) then
local Success, Error = pcall(function()
Players:WaitForChild(playerName):Kick(Message) end)
if not Success then
warn(Error)
end
GetObject[2]:Destroy()
end
end
end
-- for client only
if RunService:IsClient() then
local _lastchecked = tick()
RunService.Hearbeat:Connect()
if (tick() - _lastchecked) >= 1/60 then
if Players.LocalPlayer and self:findObject(Players.LocalPlayer.Name) and Players.LocalPlayer.Character and Players.LocalPlayer.Character:FindFirstChild("Humanoid") and Players.LocalPlayer.Character:FindFirstChild("Humanoid").WalkSpeed > 16 then
-- Players.LocalPlayer.Character:WaitForChild("Humanoid").WalkSpeed = 16
self:SafeKickClient(Players.LocalPlayer.Name, string.format("Caught change default walksped [%s]", Players.LocalPlayer.Character:WaitForChild("Humanoid").WalkSpeed))
end
_lastchecked = tick()
end
end)
repeat task.wait() until Players.LocalPlayer and Storage and self:findObject(Players.LocalPlayer.Name) == true
local GetObject = self:findObject(Players.LocalPlayer.Name, true)
Storage.ChildRemoved:Connect(function(child)
if child and child:IsA("IntValue") and child.Name == Players.LocalPlayer.Name then
Instance.new("IntValue", Storage).Name = Players.LocalPlayer.Name
end
end)
end
return Module
Sorry if there any wrong or typo and not formated i was coded it on phone
Important Note: this may able to be bypassed, have bug/glitch and need to be improved
Ah, this might be worth more if it was said two years ago when I made this post.
I’ve both forgotten this resource page and what I have said, so you may be correct or incorrect; However I do want to iterate this :-
Please, don’t waste your time trying to solidify your “Client” AntiCheat it is simply put; A waste of both resource and developer time being invested into solidifying the client.
It’s better if you set your sights on the server and how to combat exploits in your own game!
Exploiters can manipulate attributes but they’re still constricted to the rules of FilteringEnabled. Attributes changed on the client will not replicate to the server unless you have some sort of vulnerability in your game architecture that allows exploiters to make sever-sided requests to manipulate attributes through an unprotected remote.
Not sure if this was directed towards @AsynchronousMatrix or OP, but regardless there is very little benefits to trying to detect/prevent exploiters from exploiting in your experiences. Server validation is the only reliable way to minimize the effects of exploiting as a whole.
Instead of checking if they’re walking or falling, I like to separate checking the X and Z distance vs the Y distance. This way I can check their walking and their jumping/whatnot separately.