Client Raycast Firing To Server Too Many Times

I don’t really know how to word it much better, but basically I have my raycasting done client sided. Once everything like spread and the ray is created and hits a player, information like the hit body part, hit player’s name, the tool’s name, and the head, body, and limb damage are sent to the server. Here’s what that looks like

This is the client raycasting/ fire function

function RayCast(startPos, vec, rayLength)
	local hitObject, hitPos = game.Workspace:FindPartOnRay(Ray.new(startPos + (vec * .01), vec * 999), tool.Muzzle)
	if hitObject and hitPos then
		local distance = 999 - (hitPos - startPos).magnitude
		if RayIgnoreCheck(hitObject, hitPos) and distance > 0 then
			return RayCast(hitPos, vec, distance)
		end
	end
	return hitObject, hitPos
end
function FireGun()
	local targetPoint = mouse.Hit.p
	local shootDirection = (targetPoint - tool.Muzzle.Position).unit
	shootDirection = CFrame.Angles((0.5 - math.random()) * 2 * Spread,
		(0.5 - math.random()) * 2 * Spread,
		(0.5 - math.random()) * 2 * Spread) * shootDirection
	local hitObject, bulletPos = RayCast(tool.Muzzle.Position, shootDirection, 999)
	local bullet
	if hitObject then
		bullet = CreateBullet(bulletPos, hitObject)
		game.ReplicatedStorage.Fired:FireServer(tool, tool.Muzzle.Position, bulletPos, tool.Eject)
	end
	newCamKick()
	if hitObject and hitObject.Parent then
		local hitHumanoid = hitObject.Parent:FindFirstChild("Humanoid")
		if hitHumanoid then
			local hitPlayer = game.Players:GetPlayerFromCharacter(hitHumanoid.Parent)
				game.ReplicatedStorage.Body:FireServer(hitHumanoid, tool, tool.Muzzle.Position, bulletPos, tool.Eject, hitObject, 23, 27, 56)
			if bullet then
				bullet:Destroy()
				bullet = nil
			end		
		end	
	end
end

here is what happens on the server

game.ReplicatedStorage.Body.OnServerEvent:Connect(function(Player, DamageMan, Tool, StartPos, EndPos, Ejector, hitObject, limbdmg, bodydmg, headdmg)
	if hitObject.Name == 'Head' then
		DamageMan:TakeDamage(headdmg)
	elseif string.match(hitObject.Name, "Torso") or string.match(hitObject.Name, "RootPart") then
		DamageMan:TakeDamage(bodydmg)
	elseif string.match(hitObject.Name, "Leg") or string.match(hitObject.Name, "Arm") or string.match(hitObject.Name, "Hand") or string.match(hitObject.Name, "Foot") then
		DamageMan:TakeDamage(limbdmg)
	end
	DamageMan.Died:Connect(function()
		Player.leaderstats.Kills.Value = Player.leaderstats.Kills.Value + 1
		game.ReplicatedStorage.Killfeed:FireAllClients(Player.Name, Tool.Name, DamageMan.Parent.Name)
	end)
	Player.PlayerGui.Hit.crossHair.Hit.ImageColor3 = Color3.fromRGB(255,255,255)
	Player.PlayerGui.Hit.crossHair.Hit.Visible = true
	wait(0.2)
	Player.PlayerGui.Hit.crossHair.Hit.Visible = false
	Tool.Hit:Play()
end)

However, when the hit player dies, the number of kills added to the player’s leaderstats is the same as the number of shots used to kill the enemy, and this also happens with the number of indexes in the killfeed. Here’s a video of what that looks like

https://gyazo.com/f6636943181733ea3410e50aaf647b17

I’ve tried a bunch of different solutions, but as far as I know, the problem seems to be that the raycast is the only check for whether the hit player has died, and somehow the number of hits stack but not the damage. How can I fix this?

This is the problem right below. Whenever you fire the server (say you fire it 5 times when you fire 5 bullets), the OnServerEvent function will wait until the Humanoid.Died function is true and then it will run that code. So every time you fire the server it waits until they die and it gives you a kill.

I would instead replace the DamageMan.died function with the following:

if DamageMan.Health <= 0 then --check if they are dead
		Player.leaderstats.Kills.Value = Player.leaderstats.Kills.Value + 1
		game.ReplicatedStorage.Killfeed:FireAllClients(Player.Name, Tool.Name, DamageMan.Parent.Name)
end
2 Likes

I’ve already tried that, the died function is much more reliable and also doesn’t relate to the problem.

I’ve also updated the post to have a video of the problem

Yes it does relate to the problem. You fire the server many times, so whenever they die, the died event will trigger many times, thus giving them tons of kills.

1 Like

it introduces another problem, which is that the ragdoll can be shot to keep indexing the killfeed and adding to the number of kills

also doesn’t fix the original problem

1 Like

I agree with @XdJackyboiiXd2, every time you fire a bullet, a new connection is made to their humanoid.Died event. You should change itto what was suggested and test it with the change then see what happens.

1 Like

Then add another “If” statement, checking if DamageMan.Health > 0, before even damaging them again.

2 Likes

Okay so I’ve kind of combined a few of the answers below and fixed the problem like this:

firstly, I took @XdJackyboiiXd21’s solution and changed my server script to

game.ReplicatedStorage.Body.OnServerEvent:Connect(function(Player, DamageMan, Tool, StartPos, EndPos, Ejector, hitObject, limbdmg, bodydmg, headdmg)
	if hitObject.Name == 'Head' then
		DamageMan:TakeDamage(headdmg)
	elseif string.match(hitObject.Name, "Torso") or string.match(hitObject.Name, "RootPart") then
		DamageMan:TakeDamage(bodydmg)
	elseif string.match(hitObject.Name, "Leg") or string.match(hitObject.Name, "Arm") or string.match(hitObject.Name, "Hand") or string.match(hitObject.Name, "Foot") then
		DamageMan:TakeDamage(limbdmg)
	end
	if DamageMan.Health <= 0 then --check if they are dead
		Player.leaderstats.Kills.Value = Player.leaderstats.Kills.Value + 1
		game.ReplicatedStorage.Killfeed:FireAllClients(Player.Name, Tool.Name, DamageMan.Parent.Name)
	end
	Player.PlayerGui.Hit.crossHair.Hit.ImageColor3 = Color3.fromRGB(255,255,255)
	Player.PlayerGui.Hit.crossHair.Hit.Visible = true
	wait(0.2)
	Player.PlayerGui.Hit.crossHair.Hit.Visible = false
	Tool.Hit:Play()
end)

then, I edited my ragdoller to change the name of the ragdoll model to “RagDoll”, and had a simple condition for the hit event on the client raycasting to not fire if the hit object’s parent’s name is “RagDoll”

	if hitObject and hitObject.Parent then
		local hitHumanoid = hitObject.Parent:FindFirstChild("Humanoid")
		if hitHumanoid and hitHumanoid.Parent.Name ~= "RagDoll" then
			local hitPlayer = game.Players:GetPlayerFromCharacter(hitHumanoid.Parent)
				game.ReplicatedStorage.Body:FireServer(hitHumanoid, tool, tool.Muzzle.Position, bulletPos, tool.Eject, hitObject, 23, 27, 56)
			if bullet then
				bullet:Destroy()
				bullet = nil
			--bullet.Transparency = 0			
			end		
		end	
	end

thanks to everyone for the help

3 Likes