How to make a local script send data to server script with information on if a weapon does a critical or regular attack

I have a melee weapon that swings and attacks other players with a remote event and a 1 in 5 chance to do a critical hit, but I don’t know how to make the critical hit deal more damage in the server script. I was thinking adding a value and changing it with local script but it wont be server sided and I read about remote events in the developer hub but there was not anything that could fix the issue. How can I do this?

Local script

local tool = script.Parent
local hit = script:WaitForChild("Hit")
local critical = script:WaitForChild('Critical')
local player = game.Players.LocalPlayer
local char = player.Character
local humanoid = char:WaitForChild("Humanoid")

local mouse = player:GetMouse()

local hittrack = humanoid:LoadAnimation(hit)
local criticaltrack = humanoid:LoadAnimation(critical)
local meleeEvent = script.Parent:WaitForChild("MeleeEvent")

local meleeing = false
local canMelee = true
local equipped = false

tool.Equipped:Connect(function()
	equipped = true
end)

tool.Unequipped:Connect(function()
	equipped = false
end)

mouse.Button1Down:Connect(function()
	meleeing = true
	while equipped and canMelee and meleeing do
		local randomChance = math.random(1, 5)
		canMelee = false
		meleeEvent:FireServer()
		if randomChance == 5 then
			criticaltrack:Play()
			criticaltrack.Stopped:Wait()
			canMelee = true
		else
			hittrack:Play()
			hittrack.Stopped:Wait()
			canMelee = true
		end
		mouse.Button1Up:Connect(function()
			meleeing = false
		end)
	end
end)

Server script

local tool = script.Parent
local handle = tool:WaitForChild('Handle')
local swingSound = handle:WaitForChild('SwingSound')
local hitSound = handle:WaitForChild('HitSound')
local meleeEvent = tool:WaitForChild("MeleeEvent")

local damageamount = 20
local critamount = 40

local canHit = true

local function onTouch(otherPart)
	local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid")
	if humanoid and canHit and humanoid.Health > 0 then
		canHit = false
		hitSound:Play()
		humanoid:TakeDamage(damageamount)
		swingSound.Ended:Wait()
		canHit = true
	end
end

meleeEvent.OnServerEvent:Connect(function()
	script.Parent.ShovelHandle.Trail.Enabled = true
	swingSound:Play()
	handle.Touched:Connect(onTouch)
	swingSound.Ended:Wait()
	script.Parent.ShovelHandle.Trail.Enabled = false
end)

remote events would work, make the local script fireserver(), or u can explain why it didnt work?

I did make it fire the server, I just don’t know how to make the server know if it is critical or normal attack

Do the math.random chance on the server instead of on the client, you cannot trust the client. Also make sure to disconnect your touch event as your code currently has a memory leak in it - alternatively connect the touch event and when the event is fired change CanHits value.

5 Likes

Thanks this helped but the critical animation on the local script does not play when the server script does a critical attack

Animations can be played on the server as well as the client. OnServerEvent gives you the player that fired the event as it’s first parameter. OnServerEvent:Connect(function(playerWhoFiredEvent)

In your use case I recommend disconnecting your touch event when the event is fired and when a valid target is hit.

local c = nil -- this is where we will store your connection 

local function swingSword(otherPart)
    -- your hit detection code here
    if c then 
        c:Disconnect() -- disconnect the event, it will not be fired after this until reconnected
        c = nil
    end
end 

event.OnServerEvent:Connect(function(plr)
    if c then c:Disconnect() c = nil end -- if for some reason the last swing failed to disconnect or did not disconnect in time 
    c = sword.Touched:Connect(swingSword)
end)
1 Like

When I did the animations on the server script it would give an error saying Attempt to index nil with character

I have updated my reply to include some sample code.

1 Like

It still gives an error saying attempt to index nil with character in the server script

you can generate a random number between 1 & 10, if the num is between 1-5 its a normal and if 6-10 its a crit. whenever, the player clicks the mouse you can generate it and store it in a variable, then you can send that variable to the server in the FireServer(–arguments)

Oh nvm the reply got edited sorry

So in the brackets do I type it like this?

meleeEvent:FireServer(randomChance)

Remote events take in anything you want to send, but there are some exceptions but you really dont wanna focus on those.

client script:

local randomInt = math.random(1, 10)

Remote:FireServer(randomInt)
server script:

Remote.OnServerEvent:Connect(function(player, all of the stuff here you sent from the client.)
--player who fired the event will always be the first param in the remote event, 

you can read more here:Bindable Events and Functions | Roblox Creator Documentation
Read about the client-server model before that:Client-Server Model | Roblox Creator Documentation

Really hope this helped : D

1 Like

If you are playing the animation inside the swordSwing function you will need to pass the player instance into that function.

local function swordSwing(plr, otherPart)

end

-- inside remote event code
c = Sword.Touched:Connect(function(hit)
    swordSwing(plr, hit)
end)

You should never ever trust the client with information such as player data or damage as exploiters can make these values whatever they want (ie: they can make your sword do a critical hit every time)

1 Like

Do not do this, it’s highly exploitable. The critical hit chance needs to be generated on the server.

1 Like

You are correct, but I was just explaining to him how the FireServer() Arguments work.

Just a question, can local scripts be edited by exploiters in game?

Do not explain it to him in a way that is going to confuse him, that isn’t helpful to him or anyone else who could be reading this post.

1 Like

I left an article to the devhub post as well

Local scripts cannot be edited, however exploiters can fire events from their client and they can change what is passed to the server. Exploiters usually disable your client code and replace it with their own.

eg:
Your code:

UpdateCash:FireServer(50) -- your client code wants to give your player 50 cash

Exploiter code:

UpdateCash:FireServer(999999) -- exploiter code wants to give them 999999 cash

You should never ever trust the client when it comes to giving cash, dealing damage, or anything similar as it can be manipulated and usually will be.

3 Likes