Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Getting the local player from a serverscript inside StarterCharacterScripts?

So this is a punch script for whenever the player presses q, the original script was a local one inside StarterCharacterScripts. However i realised that the player can exploit in localscripts and change the debounce, therefore changing the cooldown of punches and beating everyone to death with the force of 1000 slaps.

here's the updated server-sided script that is inside StarterCharacterScripts

local UserInputService = game:GetService("UserInputService")


game.Players.PlayerAdded:Connect(function(player)
	
	if player then
		print("player found")
	else
		error("player not found aaaaa")
	end


local character = player.Character or player.CharacterAdded:Wait()
local Root = character:WaitForChild("HumanoidRootPart")

local Animation = character:WaitForChild("Humanoid"):LoadAnimation(script:WaitForChild("Animation"))

local Debounce = 2 --might change if i add a training update
local keybind = Enum.KeyCode.Q
local CanPunch = true


UserInputService.InputBegan:Connect(function(input, busy)
	if input.KeyCode == keybind and not busy then
		if CanPunch == true then 
			CanPunch = false 
			Animation:Play()
			Animation.Looped = false
			game.ReplicatedStorage.AttackRemote.Attack:FireServer()
			wait(Debounce)
			CanPunch = true
		end
	end
	end)
	
end)

now as you can see i put in a PlayerAdded which im not sure is working or not so i used a print and error which doesnt show anything in the output so im kind of clueless there

now whenever i get rid of the old localscript this no longer works so clearly the old localscript is actually working and not the new server sided script for some reason and this shows NO ERRORS in the output

here is the old localscript

local UserInputService = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local Root = character:WaitForChild("HumanoidRootPart")

local Animation = character:WaitForChild("Humanoid"):LoadAnimation(script:WaitForChild("Animation"))

--Settings//



local Debounce = 2 --might change if i add a training update
local keybind = Enum.KeyCode.Q


UserInputService.InputBegan:Connect(function(input, busy)
	if input.KeyCode == keybind and not busy then

			Animation:Play()
			Animation.Looped = false
			game.ReplicatedStorage.AttackRemote.Attack:FireServer()
			wait(Debounce)
			
		
	end
end)

i really dont know what its deal is

1 answer

An easy solution is to continue to method, but do your checks on the server where it cannot be exploited.

-- Client

local userInputService = game:GetService('UserInputService')
local Players = game:GetService('Players')
local replicatedStorage = game:GetService('ReplicatedStorage')

local Event = replicatedStorage:WaitForChild('RemoteEvent')
local Player = Players.LocalPlayer

userInputService.InputBegan:Connect(function(Input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if Input.KeyCode == Enum.KeyCode.Q then
		Event:FireServer()
	end
end)

And then for the server.

-- Server

local replicatedStorage = game:GetService('ReplicatedStorage')

local Event = replicatedStorage:WaitForChild('RemoteEvent')

local Debounces = {}
local debounceTime = 2

Event.OnServerEvent:Connect(function(Player)
	if not Collection[Player.Name] then
		Collection[Player.Name] = tick()
	end
	if tick() - Collection[Player.Name] > debounceTime then
		Collection[Player.Name] = tick()
		-- combat stuff here
	end
end)

Basically you using tick() to calculate how long since they've lasted fired the remote, and it's been longer than the debounce time then it'll swing, otherwise won't do anything, and obviously it's on the server so they cannot spoof it whatsoever.

2 comments

0

wait, whats collection?

0

It doesn't have to be named collection, collection is just an dictionary/array in which you can store data and values. In this case, for debounces.

This discussion is preserved as it was. New answers, comments, and votes are closed.