Damaging system not working correctly

I’ve been trying to make a zombie shooter game, but the damage system isn’t working correctly, everything else works perfectly fine. I kind of understand why it isn’t working, because the touched function is only firing when the bullet is shot, but I don’t understand where else to put it. Help would be greatly appreciated!

This is inside of a module script

local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local viewModels = workspace:WaitForChild("ViewModels")
local camera = workspace.CurrentCamera
local mouse = player:GetMouse()

local guns = ReplicatedStorage:WaitForChild("Guns")
local remotes = ReplicatedStorage:WaitForChild("Remotes")

local gunConnection = nil
local playingGunHoldAnimation = nil
local viewModel = nil

local isAiming = false
local isFiring = false
local isGunEquipped = false

local shootDebounce = false
local bulletDebounce = false
local reloadDebounce = false

local config = nil

local lastShootTick = tick()

local module = {}

local function DamageVictim(humanoid)
	if humanoid then
		humanoid.Health = humanoid.Health - config.Damage
	end
end

local function Shoot()
	if config.CurrentMagazine <= 0 then
		warn("Reload before you can shoot again")
		return
	end
	if (tick() - lastShootTick) > config.Firerate then
		local bulletConnection = nil
		local bullet = config.Bullet:Clone()
		bullet.CFrame = CFrame.new(viewModel.BulletLocation.Position, mouse.Hit.Position)
		bullet.Parent = workspace.Bullets


		config.CurrentMagazine = config.CurrentMagazine - 1
		config.ShootSound:Play()

		local cframe = CFrame.new()

		bulletConnection = RunService.Heartbeat:Connect(function()
			if not isGunEquipped then
				return
			end
			cframe = bullet.CFrame + bullet.CFrame.LookVector * config.BulletSpeed
			bullet.CFrame = bullet.CFrame:Lerp(cframe, 0.1)
		end)			
		
		bullet.Touched:Connect(function(hit)
			if hit.Parent.Name == player.Name then
				return
			end
			if hit.Parent:FindFirstChildOfClass("Humanoid") then
				local humanoid = hit.Parent:FindFirstChild("Humanoid")
				bullet:Destroy()
				DamageVictim(humanoid)
			end
		end)

		task.delay(5, function()
			if bullet.Parent ~= nil then
				bullet:Destroy()
			end
		end)

		lastShootTick = tick()
	else 
		return
	end
end

the DamageVictim function is to take away health, obviously, but it only works correctly if I am right up to the dummy, far away shots do not damage the victim.

Thank you for your time.

1 Like

Does the projectile visibly hit the target?

Yes it does, there is also a remote event I forgot to include, here is that script

local Remotes = game.ReplicatedStorage:WaitForChild("Remotes")
local shootEvent = Remotes.Shoot

shootEvent.OnServerEvent:Connect(function(playerWhoShot, humanoid, damage)
	print("Found humanoid")
	if humanoid.Parent.Name == playerWhoShot.Name then
		return
	end
	humanoid.Health = humanoid.Health - damage
end)

This could be the solution: place the touched event before you move the bullet.

It did not work correctly, although it started printing “Found humanoid”, but I think it was talking about the player humanoid.

Also, where did you fire the event above? I thought you were using a touch event to deal damage not a remote event. BTW, make sure you handle things the right way with client vs server interactions. Things done on a local script is not visible to the server and the rest of the players, also keep in mind exploiters can manipulate remote event sends except the player value.

.Touched is not guaranteed to fire at high speed. Use a Raycast to detect hits instead of .Touched. Replace the projectile simulation with an instant ray hit:

local function Shoot()
	if config.CurrentMagazine <= 0 then return end
	if (tick() - lastShootTick) <= config.Firerate then return end

	local origin = viewModel.BulletLocation.Position
	local direction = (mouse.Hit.Position - origin).Unit * config.Range

	local result = workspace:Raycast(origin, direction, RaycastParams.new())

	if result and result.Instance and result.Instance.Parent:FindFirstChild("Humanoid") then
		local humanoid = result.Instance.Parent:FindFirstChild("Humanoid")
		remotes.Shoot:FireServer(humanoid, config.Damage)
	end

	config.CurrentMagazine -= 1
	config.ShootSound:Play()
	lastShootTick = tick()
end

Also, for; shootEvent.OnServerEvent:Connect(function(playerWhoShot, humanoid, damage)
You’re sending damage from the client here… that would be hackable.

3 Likes

It works, thank you very much!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.