So after going through a few tutorials on Youtube regarding module script I have tried my best to write scripts (especially so exploiters can’t manipulate the leaderboard) I have outlined my entire process here: Module Script Problem - Obsidian Publish as its just easier for me in terms of noting down and diagramming etc… so apologies for the external link. But as per this link in short this is what I am trying to achieve and any advice on this would be much appericiated.
Player jumps in air
Via module script (so score can’t be manipulated by exploiter) a function detects jump and adds 1 point to the roblox leaderboard.
As you can see my logic for doing this works, what don’t work is trying to do it more server side / within a module script to prevent exploitation / manipulation of the score. That is what I mainly need advice on going forwards as what I have tried so far produces zero errors so I am a bit stuck, it simply and literally does not work as intended. Overall how do I pass the jump score function into the module script?
The exploiter can still manipulate the constants/variables in the module script using the debug library. You should just keep all the important logic in the server like this:
--//Services
local Players = game:GetService("Players")
--//Functions
Players.PlayerAdded:Connect(function(player)
local stats = Instance.new("IntValue")
stats.Name = "leaderstats"
local jumps = Instance.new("IntValue")
jumps.Name = "Jumps"
jumps.Parent = stats
stats.Parent = player
player.CharacterAdded:Connect(function(character)
local Humanoid = character:WaitForChild("Humanoid")
Humanoid.Jumping:Connect(function(isJumping)
if isJumping then
jumps.Value += 1
end
end)
end)
end)
Also if you’re just looking for some more info on the exploit, it goes something like this:
local module = require(script.Parent.ModuleScript)
--//3 is the constant index and 100 is the value set
setconstant(module.playerJumpedModule, 3, 100)
When you say put it in the server what do you mean exactly by that? Can you be more specific? What folder etc…? Do I still do it as a module script?
Thanks, but its automatic published from https://obsidian.md its just easy to do that because I can show my thought process to people and what I have tried easier.
What I mean is that all the important logic should be done server-side, meaning there’s no way for the client to interfere with the logic. Try pasting my script into a script that’s in ServerScriptService. You shouldn’t use module scripts unless you’re using the same code over again.
That kinda works, I got it to the point where it adds a score on jumping but not every time I also have this script recently in StarterPlayer → StarterCharacterScripts so I think this could be effecting it, just not sure how its like the jump score is delayed?:
local canjump = true
wait(2)
if script.Parent.ClassName == "Model" then
local character = script.Parent
print(character.Name)
character.Humanoid.UseJumpPower = true
character.Humanoid.JumpPower = 0
local function jump()
if canjump == true then
canjump = false
character.Humanoid.Jump = true
character.Humanoid.JumpPower = 100
wait(0.05)
character.Humanoid.JumpPower = 0
wait(1.5)
canjump = true
end
end
character.Humanoid:GetPropertyChangedSignal("Jump"):Connect(jump)
end
Update I just disabled this script entirely and it adds the jumps but still not on every jump, its delayed like that, I can’t work out how?
Your local script shouldn’t affect the server, I just made a mistake.
Here’s a more reliable check for when a player jumps: (switch out your server script with this)
--//Services
local Players = game:GetService("Players")
--//Functions
Players.PlayerAdded:Connect(function(player)
local stats = Instance.new("IntValue")
stats.Name = "leaderstats"
local jumps = Instance.new("IntValue")
jumps.Name = "Jumps"
jumps.Parent = stats
stats.Parent = player
player.CharacterAdded:Connect(function(character)
local Humanoid = character:WaitForChild("Humanoid")
local jumpDebounce = false
Humanoid:GetPropertyChangedSignal("Jump"):Connect(function()
if Humanoid.Jump and not jumpDebounce then
jumpDebounce = true
jumps.Value += 1
task.wait(0.5)
jumpDebounce = false
end
end)
end)
end)
That was fast I was nearly there myself with a similar solution haha, thanks! That works perfectly now, I just need to balance the timings with the jump delay
No problem, if you have any more questions, feel free to ask.
Also, since I forgot to explain earlier, I added the debounce so that if an exploiter rapidly changes their jump value on their humanoid, the server will only add their jump if there is no debounce.
wait(2)
if script.Parent.ClassName == "Model" then
local character = script.Parent
print(character.Name)
character.Humanoid.UseJumpPower = true
character.Humanoid.JumpPower = 0
local function jump()
if canjump == true then
canjump = false
character.Humanoid.Jump = true
character.Humanoid.JumpPower = 65
wait(5.0)
character.Humanoid.JumpPower = 0
wait(5.0)
canjump = true
end
end
character.Humanoid:GetPropertyChangedSignal("Jump"):Connect(jump)
end
I am now having trouble with this seperate script, initially I just wanted it so the player can’t hold down the space bar, instead they have to do a key press each time for a jump, it seems no matter what timing I use on the jump delay, disabiling and the task.wait(5.0) (I changed to 5.0 as well) on the score script above there seems to be a way to up the score too quickly by holding down the spacebar.
First off, change your server-script to this: (I added a longer cooldown)
--//Services
local Players = game:GetService("Players")
--//Functions
Players.PlayerAdded:Connect(function(player)
local stats = Instance.new("IntValue")
stats.Name = "leaderstats"
local jumps = Instance.new("IntValue")
jumps.Name = "Jumps"
jumps.Parent = stats
stats.Parent = player
player.CharacterAdded:Connect(function(character)
local Humanoid = character:WaitForChild("Humanoid")
local jumpDebounce = false
Humanoid:GetPropertyChangedSignal("Jump"):Connect(function()
if Humanoid.Jump and not jumpDebounce then
jumpDebounce = true
jumps.Value += 1
task.wait(0.7)
jumpDebounce = false
end
end)
end)
end)
Next, add a local script into StarterCharacterScripts:
In the local script, paste this:
--//Services
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
--//Functions
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
--//Controls
local jump = false
--//Tables
local Connections = {}
--//Functions
UserInputService.JumpRequest:Connect(function()
if Humanoid.FloorMaterial == Enum.Material.Air then
jump = true
Humanoid.JumpHeight = 0
Connections.FloorMaterial = Humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
if Humanoid.FloorMaterial ~= Enum.Material.Air then
Connections.FloorMaterial:Disconnect()
jump = false
end
end)
end
end)
UserInputService.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space and not jump then
Humanoid.JumpHeight = 7.2
Humanoid.Jump = true
end
end)
(just a small thing, but I just want to say that you are probably one of the most patient person on this forum lol)